From 1a458aa4501d4ce2895a53044e36e3b036293478 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 18 Nov 2019 15:00:33 -0800 Subject: [PATCH 01/22] 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 c5e843832152..0644e963f8ea 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 7514f580813e..eb404c406385 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 7514f580813e..eb404c406385 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 88e5c6bef9fb..3fabebd2001f 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 7514f580813e..eb404c406385 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 7514f580813e..eb404c406385 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 7514f580813e..eb404c406385 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 02/22] 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 eb404c406385..d7a99025cc98 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 eb404c406385..d7a99025cc98 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 eb404c406385..d7a99025cc98 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 eb404c406385..d7a99025cc98 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 eb404c406385..d7a99025cc98 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 03/22] 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 f6ad5246d8ef..38b02b47d7c5 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 ebe38f1f0601..b73dd0ab4f78 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 92948eeffc6d..14fe03c34722 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 c557f43f1c7e..5c1c27541c6e 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 6c445fb76c1b..666edf7a1779 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 2d3a742b7f0e9cf49502cb31820bfbbc419f04e7 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 6 Feb 2020 13:41:00 -0800 Subject: [PATCH 04/22] 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 4cf09b6e4817..a41488650364 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 0644e963f8ea..f1e4598220b5 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 e5e666c020b1..852f84b84b97 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 6420d52ee6d7..b291aaebd1a9 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 5c12a3d21738..32caabbe079d 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 2a012447a689..1d3ad55c2ef3 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 4319cb865874..90d5c8690a65 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 4319cb865874..90d5c8690a65 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 05/22] 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 e357c96782b7..c224bbc32713 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 1d5971f8eca714bc36e3366a1c3772ae194ed44d Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 12 Feb 2020 13:29:21 -0800 Subject: [PATCH 06/22] 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 7778ebb76c06..343ffc27db5d 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 b291aaebd1a9..1e14f92d0a6f 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 ff876aaedf0815f4fab688a1f66dc7a59c69d2e3 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 18 Feb 2020 09:48:21 -0800 Subject: [PATCH 07/22] 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 3b73052432d3..167c8d419fab 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 594f572f25f0..4659e258bcb8 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 ba8ebe9f3a7db12a086df40b3ebbe7d69143fcf9 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 10 Mar 2020 11:41:59 -0700 Subject: [PATCH 08/22] 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 bcaa0ab3f25d..f44773f0fd33 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 07d0c8ea717f..cb15cebf59c1 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 824799db8129..f08858d1a9ca 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 824799db8129..f08858d1a9ca 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 a0823a2582614bd2f9ab0c7e3514df523494adc1 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 12 Mar 2020 15:06:17 -0700 Subject: [PATCH 09/22] 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 f44773f0fd33..62a45339b3d3 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 cb15cebf59c1..dc765b62097b 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 ee75a2f28e46..04f439636d93 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 f08858d1a9ca..da51da90a500 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 f08858d1a9ca..da51da90a500 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 d529fedbadfea238191337a82ff14c08da53610a Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 20 Mar 2020 11:00:54 -0700 Subject: [PATCH 10/22] 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 5e3a1d154556..00077ec850cd 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 dc765b62097b..6df7ff9737cb 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 b579e6aabe3c78366572f9b75e57a1d44a2f258a Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 31 Mar 2020 12:56:52 -0700 Subject: [PATCH 11/22] 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 1e78ae87f40f..517ef7099c0f 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 fd915bb5b1c6fabfd65623bb406d9d0600c48ed2 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 2 Apr 2020 14:56:11 -0700 Subject: [PATCH 12/22] 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 abb62b9a021c..55378ed36ef3 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 dacbc1376ca4e34938e779c027c980f7c45ae5b8 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Wed, 8 Apr 2020 10:36:04 +0100 Subject: [PATCH 13/22] 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 353d012e3396..3c7e320dff6c 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 02d962844c8a..c5fdcbed5f95 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 626e50925f95..2d8b52f86225 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 48beeed57913..ecc9d4d0c097 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 d0eac290a56d..5b014ca72fc7 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 0ab52f845a80..76c8c442db99 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 816b5ea5310b..9177a4197b6e 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 5bb7370d11c7..1446e18a4f8b 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 2dc645174652..f03c0300e254 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 58e2d93f95e9..7ddda7c60de2 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 edd6cb027b06..6a6c482f69d3 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 9db6b8f1e2b63c1602ae6dcfe3d0aedaf01cf728 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Wed, 8 Apr 2020 11:42:30 +0100 Subject: [PATCH 14/22] 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 76c8c442db99..44ef01cccf78 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 07d913125691f9386d85ece5db547f10f1258717 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Wed, 8 Apr 2020 12:14:40 +0100 Subject: [PATCH 15/22] 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 8795569d5bc1..89cad6528c64 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 a0b26d66a4118e1eb9c45ff9297b9144eeb8018e Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 8 Apr 2020 13:55:41 -0700 Subject: [PATCH 16/22] 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 12857dd05e99..9385d6730e4d 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 17/22] 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 9385d6730e4d..61d941a6f44c 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 18/22] 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 61d941a6f44c..523a64576b1e 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 19/22] 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 b6d834f1fddb..38216872f2b8 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 b6d834f1fddb..38216872f2b8 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 b6d834f1fddb..38216872f2b8 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 b6d834f1fddb..38216872f2b8 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 b6d834f1fddb..38216872f2b8 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 20/22] 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 55378ed36ef3..1dd1d9ac4cc1 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 21/22] 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 523a64576b1e..dbeefae48808 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 87791778393533ff59b6971cf49f7846fb846174 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 13 Apr 2020 14:03:02 -0700 Subject: [PATCH 22/22] 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 64faf3331ad3..10ec2a63dc2d 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