From fd807d46d6c59338bbc2f7c09252bdbe3447e487 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 27 Jan 2020 16:38:07 -0800 Subject: [PATCH 1/4] C++: IR dataflow through modeled functions --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 54 ++++++++++++++++++- .../dataflow/taint-tests/test_diff.expected | 4 -- .../dataflow/taint-tests/test_ir.expected | 4 ++ 3 files changed, 57 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 24598bdaf12..23a94837620 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -6,6 +6,7 @@ private import cpp private import semmle.code.cpp.ir.IR private import semmle.code.cpp.controlflow.IRGuards private import semmle.code.cpp.ir.ValueNumbering +private import semmle.code.cpp.models.interfaces.DataFlow /** * A newtype wrapper to prevent accidental casts between `Node` and @@ -282,7 +283,58 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction // for variables that have escaped: for soundness, the IR has to assume that // every write to an unknown address can affect every escaped variable, and // this assumption shows up as data flowing through partial chi operands. - iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom + iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom or + // Flow from argument to return value + iTo = any(CallInstruction call | + exists(int indexIn | + modelFlowToReturnValue(call.getStaticCallTarget(), indexIn) and + iFrom = getACallArgumentOrIndirection(call, indexIn) + ) + ) + or + // Flow from input argument to output argument + // TODO: This won't work in practice as long as all aliased memory is tracked + // together in a single virtual variable. + iTo = any(WriteSideEffectInstruction outNode | + exists(CallInstruction call, int indexIn, int indexOut | + modelFlowToParameter(call.getStaticCallTarget(), indexIn, indexOut) and + iFrom = getACallArgumentOrIndirection(call, indexIn) and + outNode.getIndex() = indexOut and + outNode.getPrimaryInstruction() = call + ) + ) +} + +/** + * Get an instruction that goes into argument `argumentIndex` of `call`. This + * can be either directly or through one pointer indirection. + */ +private Instruction getACallArgumentOrIndirection(CallInstruction call, int argumentIndex) { + result = call.getPositionalArgument(argumentIndex) + or + exists(ReadSideEffectInstruction readSE | + // TODO: why are read side effect operands imprecise? + result = readSE.getSideEffectOperand().getAnyDef() and + readSE.getPrimaryInstruction() = call and + readSE.getIndex() = argumentIndex + ) +} + +private predicate modelFlowToParameter(Function f, int parameterIn, int parameterOut) { + exists(FunctionInput modelIn, FunctionOutput modelOut | + f.(DataFlowFunction).hasDataFlow(modelIn, modelOut) and + (modelIn.isParameter(parameterIn) or modelIn.isParameterDeref(parameterIn)) and + modelOut.isParameterDeref(parameterOut) + ) +} + +private predicate modelFlowToReturnValue(Function f, int parameterIn) { + // Data flow from parameter to return value + exists(FunctionInput modelIn, FunctionOutput modelOut | + f.(DataFlowFunction).hasDataFlow(modelIn, modelOut) and + (modelIn.isParameter(parameterIn) or modelIn.isParameterDeref(parameterIn)) and + (modelOut.isReturnValue() or modelOut.isReturnValueDeref()) + ) } /** diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index 9354f098533..bd7652ff5bb 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -24,10 +24,6 @@ | taint.cpp:261:7:261:7 | taint.cpp:258:7:258:12 | AST only | | taint.cpp:351:7:351:7 | taint.cpp:330:6:330:11 | AST only | | taint.cpp:352:7:352:7 | taint.cpp:330:6:330:11 | AST only | -| taint.cpp:372:7:372:7 | taint.cpp:365:24:365:29 | AST only | -| taint.cpp:374:7:374:7 | taint.cpp:365:24:365:29 | AST only | -| taint.cpp:382:7:382:7 | taint.cpp:377:23:377:28 | AST only | -| taint.cpp:391:7:391:7 | taint.cpp:385:27:385:32 | AST only | | taint.cpp:423:7:423:7 | taint.cpp:422:14:422:19 | AST only | | taint.cpp:424:9:424:17 | taint.cpp:422:14:422:19 | AST only | | taint.cpp:429:7:429:7 | taint.cpp:428:13:428:18 | IR only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected index 258a2cca7c5..9e920e23dfc 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected @@ -15,4 +15,8 @@ | taint.cpp:291:7:291:7 | y | taint.cpp:275:6:275:11 | call to source | | taint.cpp:337:7:337:7 | t | taint.cpp:330:6:330:11 | call to source | | taint.cpp:350:7:350:7 | t | taint.cpp:330:6:330:11 | call to source | +| taint.cpp:372:7:372:7 | a | taint.cpp:365:24:365:29 | source | +| taint.cpp:374:7:374:7 | c | taint.cpp:365:24:365:29 | source | +| taint.cpp:382:7:382:7 | a | taint.cpp:377:23:377:28 | source | +| taint.cpp:391:7:391:7 | a | taint.cpp:385:27:385:32 | source | | taint.cpp:429:7:429:7 | b | taint.cpp:428:13:428:18 | call to source | From 1b9e37534172fff65673778fb452b26c639809e3 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 27 Jan 2020 16:44:41 -0800 Subject: [PATCH 2/4] C++: Move getACallArgumentOrIndirection --- .../cpp/ir/dataflow/DefaultTaintTracking.qll | 19 ++----------------- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 17 +++++++++++------ 2 files changed, 13 insertions(+), 23 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 5005d694a15..af2d617fafe 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -163,7 +163,7 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) { i2 = any(CallInstruction call | exists(int indexIn | modelTaintToReturnValue(call.getStaticCallTarget(), indexIn) and - i1 = getACallArgumentOrIndirection(call, indexIn) + i1 = DataFlow::getACallArgumentOrIndirection(call, indexIn) ) ) or @@ -175,28 +175,13 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) { i2 = any(WriteSideEffectInstruction outNode | exists(CallInstruction call, int indexIn, int indexOut | modelTaintToParameter(call.getStaticCallTarget(), indexIn, indexOut) and - i1 = getACallArgumentOrIndirection(call, indexIn) and + i1 = DataFlow::getACallArgumentOrIndirection(call, indexIn) and outNode.getIndex() = indexOut and outNode.getPrimaryInstruction() = call ) ) } -/** - * Get an instruction that goes into argument `argumentIndex` of `call`. This - * can be either directly or through one pointer indirection. - */ -private Instruction getACallArgumentOrIndirection(CallInstruction call, int argumentIndex) { - result = call.getPositionalArgument(argumentIndex) - or - exists(ReadSideEffectInstruction readSE | - // TODO: why are read side effect operands imprecise? - result = readSE.getSideEffectOperand().getAnyDef() and - readSE.getPrimaryInstruction() = call and - readSE.getIndex() = argumentIndex - ) -} - private predicate modelTaintToParameter(Function f, int parameterIn, int parameterOut) { exists(FunctionInput modelIn, FunctionOutput modelOut | f.(TaintFunction).hasTaintFlow(modelIn, modelOut) and diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 23a94837620..3e1fb7dde2a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -265,11 +265,15 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) { } private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo) { - iTo.(CopyInstruction).getSourceValue() = iFrom or - iTo.(PhiInstruction).getAnOperand().getDef() = iFrom or + iTo.(CopyInstruction).getSourceValue() = iFrom + or + iTo.(PhiInstruction).getAnOperand().getDef() = iFrom + or // Treat all conversions as flow, even conversions between different numeric types. - iTo.(ConvertInstruction).getUnary() = iFrom or - iTo.(InheritanceConversionInstruction).getUnary() = iFrom or + iTo.(ConvertInstruction).getUnary() = iFrom + or + iTo.(InheritanceConversionInstruction).getUnary() = iFrom + or // A chi instruction represents a point where a new value (the _partial_ // operand) may overwrite an old value (the _total_ operand), but the alias // analysis couldn't determine that it surely will overwrite every bit of it or @@ -283,7 +287,8 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction // for variables that have escaped: for soundness, the IR has to assume that // every write to an unknown address can affect every escaped variable, and // this assumption shows up as data flowing through partial chi operands. - iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom or + iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom + or // Flow from argument to return value iTo = any(CallInstruction call | exists(int indexIn | @@ -309,7 +314,7 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction * Get an instruction that goes into argument `argumentIndex` of `call`. This * can be either directly or through one pointer indirection. */ -private Instruction getACallArgumentOrIndirection(CallInstruction call, int argumentIndex) { +Instruction getACallArgumentOrIndirection(CallInstruction call, int argumentIndex) { result = call.getPositionalArgument(argumentIndex) or exists(ReadSideEffectInstruction readSE | From 83d611de11ff7543507193d1022d764e95ad313b Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 30 Jan 2020 15:19:59 -0800 Subject: [PATCH 3/4] C++: don't conflate pointers in data flow --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 57 +++++++++++++------ .../defaulttainttracking.cpp | 9 +++ .../DefaultTaintTracking/tainted.expected | 8 +++ .../DefaultTaintTracking/test_diff.expected | 6 ++ .../dataflow/taint-tests/test_diff.expected | 3 + .../dataflow/taint-tests/test_ir.expected | 3 - 6 files changed, 67 insertions(+), 19 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 01fee2728a7..5cca7894997 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -291,25 +291,50 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction // for now. iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom or - // Flow from argument to return value - iTo = any(CallInstruction call | - exists(int indexIn | - modelFlowToReturnValue(call.getStaticCallTarget(), indexIn) and - iFrom = getACallArgumentOrIndirection(call, indexIn) - ) - ) - or - // Flow from input argument to output argument - // TODO: This won't work in practice as long as all aliased memory is tracked - // together in a single virtual variable. - iTo = any(WriteSideEffectInstruction outNode | - exists(CallInstruction call, int indexIn, int indexOut | - modelFlowToParameter(call.getStaticCallTarget(), indexIn, indexOut) and - iFrom = getACallArgumentOrIndirection(call, indexIn) and - outNode.getIndex() = indexOut and + // Flow through modeled functions + modelFlow(iFrom, iTo) +} + +private predicate modelFlow(Instruction iFrom, Instruction iTo) { + exists( + CallInstruction call, DataFlowFunction func, FunctionInput modelIn, FunctionOutput modelOut + | + call.getStaticCallTarget() = func and + func.hasDataFlow(modelIn, modelOut) + | + ( + modelOut.isReturnValue() and + iTo = call + or + // TODO: Add write side effects for return values + modelOut.isReturnValueDeref() and + iTo = call + or + exists(WriteSideEffectInstruction outNode | + modelOut.isParameterDeref(outNode.getIndex()) and + iTo = outNode and outNode.getPrimaryInstruction() = call ) + // TODO: add write side effects for qualifiers + ) and + ( + exists(int index | + modelIn.isParameter(index) and + iFrom = call.getPositionalArgument(index) + ) + or + exists(int index, ReadSideEffectInstruction read | + modelIn.isParameterDeref(index) and + read.getIndex() = index and + read.getPrimaryInstruction() = call and + iFrom = read.getSideEffectOperand().getAnyDef() + ) + or + modelIn.isQualifierAddress() and + iFrom = call.getThisArgument() + // TODO: add read side effects for qualifiers ) + ) } /** diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/defaulttainttracking.cpp b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/defaulttainttracking.cpp index ebe38f1f060..02ae1e07154 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/defaulttainttracking.cpp +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/defaulttainttracking.cpp @@ -77,4 +77,13 @@ void test_dynamic_cast() { reinterpret_cast(b2)->f(getenv("VAR")); dynamic_cast(b2)->f(getenv("VAR")); // tainted [FALSE POSITIVE] +} + +namespace std { + template< class T > + T&& move( T&& t ) noexcept; +} + +void test_std_move() { + sink(std::move(getenv("VAR"))); } \ No newline at end of file diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected index 92948eeffc6..ddb07575064 100644 --- a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected +++ b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/tainted.expected @@ -89,6 +89,14 @@ | 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:18:88:23 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 | +| defaulttainttracking.cpp:88:18:88:23 | call to getenv | defaulttainttracking.cpp:84:17:84:17 | t | +| defaulttainttracking.cpp:88:18:88:23 | call to getenv | defaulttainttracking.cpp:88:8:88:16 | call to move | +| defaulttainttracking.cpp:88:18:88:23 | call to getenv | defaulttainttracking.cpp:88:8:88:32 | (const char *)... | +| defaulttainttracking.cpp:88:18:88:23 | call to getenv | defaulttainttracking.cpp:88:8:88:32 | (reference dereference) | +| defaulttainttracking.cpp:88:18:88:23 | call to getenv | defaulttainttracking.cpp:88:18:88:23 | call to getenv | +| defaulttainttracking.cpp:88:18:88:23 | call to getenv | defaulttainttracking.cpp:88:18:88:30 | (reference to) | +| defaulttainttracking.cpp:88:18:88:23 | call to getenv | test_diff.cpp:1:11:1:20 | p#0 | | test_diff.cpp:92:10:92:13 | argv | defaulttainttracking.cpp:9:11:9:20 | p#0 | | test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:1:11:1:20 | p#0 | | test_diff.cpp:92:10:92:13 | argv | test_diff.cpp:92:10:92:13 | argv | diff --git a/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected b/cpp/ql/test/library-tests/dataflow/DefaultTaintTracking/test_diff.expected index c557f43f1c7..27aad1725a8 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,12 @@ | 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:18:88:23 | call to getenv | defaulttainttracking.cpp:9:11:9:20 | p#0 | IR only | +| defaulttainttracking.cpp:88:18:88:23 | call to getenv | defaulttainttracking.cpp:88:8:88:16 | call to move | IR only | +| defaulttainttracking.cpp:88:18:88:23 | call to getenv | defaulttainttracking.cpp:88:8:88:32 | (const char *)... | IR only | +| defaulttainttracking.cpp:88:18:88:23 | call to getenv | defaulttainttracking.cpp:88:8:88:32 | (reference dereference) | IR only | +| defaulttainttracking.cpp:88:18:88:23 | call to getenv | defaulttainttracking.cpp:88:18:88:30 | (reference to) | IR only | +| defaulttainttracking.cpp:88:18:88:23 | 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/taint-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected index f41cc776510..7680193da16 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected @@ -32,6 +32,9 @@ | taint.cpp:261:7:261:7 | taint.cpp:258:7:258:12 | AST only | | taint.cpp:351:7:351:7 | taint.cpp:330:6:330:11 | AST only | | taint.cpp:352:7:352:7 | taint.cpp:330:6:330:11 | AST only | +| taint.cpp:372:7:372:7 | taint.cpp:365:24:365:29 | AST only | +| taint.cpp:374:7:374:7 | taint.cpp:365:24:365:29 | AST only | +| taint.cpp:391:7:391:7 | taint.cpp:385:27:385:32 | AST only | | taint.cpp:423:7:423:7 | taint.cpp:422:14:422:19 | AST only | | taint.cpp:424:9:424:17 | taint.cpp:422:14:422:19 | AST only | | taint.cpp:429:7:429:7 | taint.cpp:428:13:428:18 | IR only | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected index 49ff8144a6e..b38de345220 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected @@ -17,9 +17,6 @@ | taint.cpp:291:7:291:7 | y | taint.cpp:275:6:275:11 | call to source | | taint.cpp:337:7:337:7 | t | taint.cpp:330:6:330:11 | call to source | | taint.cpp:350:7:350:7 | t | taint.cpp:330:6:330:11 | call to source | -| taint.cpp:372:7:372:7 | a | taint.cpp:365:24:365:29 | source | -| taint.cpp:374:7:374:7 | c | taint.cpp:365:24:365:29 | source | | taint.cpp:382:7:382:7 | a | taint.cpp:377:23:377:28 | source | -| taint.cpp:391:7:391:7 | a | taint.cpp:385:27:385:32 | source | | taint.cpp:429:7:429:7 | b | taint.cpp:428:13:428:18 | call to source | | taint.cpp:430:9:430:14 | member | taint.cpp:428:13:428:18 | call to source | From 1576bcfa3f1adce5df4354cc6645b2f6181d3699 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 4 Feb 2020 12:08:03 -0800 Subject: [PATCH 4/4] C++: remove unused predicates --- .../cpp/ir/dataflow/DefaultTaintTracking.qll | 4 +-- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 32 ------------------- 2 files changed, 2 insertions(+), 34 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 2e5a742b796..fea47e1b5bd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -172,7 +172,7 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) { any(CallInstruction call | exists(int indexIn | modelTaintToReturnValue(call.getStaticCallTarget(), indexIn) and - i1 = DataFlow::getACallArgumentOrIndirection(call, indexIn) + i1 = getACallArgumentOrIndirection(call, indexIn) ) ) or @@ -185,7 +185,7 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) { any(WriteSideEffectInstruction outNode | exists(CallInstruction call, int indexIn, int indexOut | modelTaintToParameter(call.getStaticCallTarget(), indexIn, indexOut) and - i1 = DataFlow::getACallArgumentOrIndirection(call, indexIn) and + i1 = getACallArgumentOrIndirection(call, indexIn) and outNode.getIndex() = indexOut and outNode.getPrimaryInstruction() = call ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 5cca7894997..9428935ad7d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -337,38 +337,6 @@ private predicate modelFlow(Instruction iFrom, Instruction iTo) { ) } -/** - * Get an instruction that goes into argument `argumentIndex` of `call`. This - * can be either directly or through one pointer indirection. - */ -Instruction getACallArgumentOrIndirection(CallInstruction call, int argumentIndex) { - result = call.getPositionalArgument(argumentIndex) - or - exists(ReadSideEffectInstruction readSE | - // TODO: why are read side effect operands imprecise? - result = readSE.getSideEffectOperand().getAnyDef() and - readSE.getPrimaryInstruction() = call and - readSE.getIndex() = argumentIndex - ) -} - -private predicate modelFlowToParameter(Function f, int parameterIn, int parameterOut) { - exists(FunctionInput modelIn, FunctionOutput modelOut | - f.(DataFlowFunction).hasDataFlow(modelIn, modelOut) and - (modelIn.isParameter(parameterIn) or modelIn.isParameterDeref(parameterIn)) and - modelOut.isParameterDeref(parameterOut) - ) -} - -private predicate modelFlowToReturnValue(Function f, int parameterIn) { - // Data flow from parameter to return value - exists(FunctionInput modelIn, FunctionOutput modelOut | - f.(DataFlowFunction).hasDataFlow(modelIn, modelOut) and - (modelIn.isParameter(parameterIn) or modelIn.isParameterDeref(parameterIn)) and - (modelOut.isReturnValue() or modelOut.isReturnValueDeref()) - ) -} - /** * Holds if data flows from `source` to `sink` in zero or more local * (intra-procedural) steps.