Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f235b99

Browse files
author
Robert Marsh
authored
Merge pull request #11374 from MathiasVP/indirect-outnodes-are-post-update-nodes
C++: Field flow through reference-returning functions
2 parents 7c6918d + 6233722 commit f235b99

4 files changed

Lines changed: 87 additions & 11 deletions

File tree

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 55 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -596,10 +596,33 @@ predicate indirectReturnOutNodeInstruction0(
596596
instructionForfullyConvertedCall(instr, call)
597597
}
598598

599+
/**
600+
* Holds if `node` is an indirect operand with columns `(operand, indirectionIndex)`, and
601+
* `operand` represents a use of the fully converted value of `call`.
602+
*/
603+
private predicate hasOperand(Node node, CallInstruction call, int indirectionIndex, Operand operand) {
604+
indirectReturnOutNodeOperand0(call, operand, indirectionIndex) and
605+
hasOperandAndIndex(node, operand, indirectionIndex)
606+
}
607+
608+
/**
609+
* Holds if `node` is an indirect instruction with columns `(instr, indirectionIndex)`, and
610+
* `instr` represents a use of the fully converted value of `call`.
611+
*
612+
* Note that `hasOperand(node, _, _, _)` implies `not hasInstruction(node, _, _, _)`.
613+
*/
614+
private predicate hasInstruction(
615+
Node node, CallInstruction call, int indirectionIndex, Instruction instr
616+
) {
617+
indirectReturnOutNodeInstruction0(call, instr, indirectionIndex) and
618+
hasInstructionAndIndex(node, instr, indirectionIndex)
619+
}
620+
599621
/**
600622
* INTERNAL: do not use.
601623
*
602-
* A node representing the value of a function call.
624+
* A node representing the indirect value of a function call (i.e., a value hidden
625+
* behind a number of indirections).
603626
*/
604627
class IndirectReturnOutNode extends Node {
605628
CallInstruction call;
@@ -608,20 +631,43 @@ class IndirectReturnOutNode extends Node {
608631
IndirectReturnOutNode() {
609632
// Annoyingly, we need to pick the fully converted value as the output of the function to
610633
// make flow through in the shared dataflow library work correctly.
611-
exists(Operand operand |
612-
indirectReturnOutNodeOperand0(call, operand, indirectionIndex) and
613-
hasOperandAndIndex(this, operand, indirectionIndex)
614-
)
634+
hasOperand(this, call, indirectionIndex, _)
615635
or
616-
exists(Instruction instr |
617-
indirectReturnOutNodeInstruction0(call, instr, indirectionIndex) and
618-
hasInstructionAndIndex(this, instr, indirectionIndex)
619-
)
636+
hasInstruction(this, call, indirectionIndex, _)
620637
}
621638

622639
CallInstruction getCallInstruction() { result = call }
623640

624641
int getIndirectionIndex() { result = indirectionIndex }
642+
643+
/** Gets the operand associated with this node, if any. */
644+
Operand getOperand() { hasOperand(this, call, indirectionIndex, result) }
645+
646+
/** Gets the instruction associated with this node, if any. */
647+
Instruction getInstruction() { hasInstruction(this, call, indirectionIndex, result) }
648+
}
649+
650+
/**
651+
* An `IndirectReturnOutNode` which is used as a destination of a store operation.
652+
* When it's used for a store operation it's useful to have this be a `PostUpdateNode` for
653+
* the shared dataflow library's flow-through mechanism to detect flow in cases such as:
654+
* ```cpp
655+
* struct MyInt {
656+
* int i;
657+
* int& getRef() { return i; }
658+
* };
659+
* ...
660+
* MyInt mi;
661+
* mi.getRef() = source(); // this is detected as a store to `i` via flow-through.
662+
* sink(mi.i);
663+
* ```
664+
*/
665+
private class PostIndirectReturnOutNode extends IndirectReturnOutNode, PostUpdateNode {
666+
PostIndirectReturnOutNode() {
667+
any(StoreInstruction store).getDestinationAddressOperand() = this.getOperand()
668+
}
669+
670+
override Node getPreUpdateNode() { result = this }
625671
}
626672

627673
private Type getTypeImpl(Type t, int indirectionIndex) {

cpp/ql/test/library-tests/dataflow/fields/dataflow-ir-consistency.expected

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ compatibleTypesReflexive
2121
unreachableNodeCCtx
2222
localCallNodes
2323
postIsNotPre
24+
| A.cpp:98:12:98:18 | new indirection | PostUpdateNode should not equal its pre-update node. |
25+
| B.cpp:6:15:6:24 | new indirection | PostUpdateNode should not equal its pre-update node. |
26+
| B.cpp:15:15:15:27 | new indirection | PostUpdateNode should not equal its pre-update node. |
27+
| C.cpp:22:12:22:21 | new indirection | PostUpdateNode should not equal its pre-update node. |
28+
| C.cpp:24:16:24:25 | new indirection | PostUpdateNode should not equal its pre-update node. |
29+
| D.cpp:28:15:28:24 | new indirection | PostUpdateNode should not equal its pre-update node. |
30+
| D.cpp:35:15:35:24 | new indirection | PostUpdateNode should not equal its pre-update node. |
31+
| D.cpp:42:15:42:24 | new indirection | PostUpdateNode should not equal its pre-update node. |
32+
| D.cpp:49:15:49:24 | new indirection | PostUpdateNode should not equal its pre-update node. |
33+
| D.cpp:56:15:56:24 | new indirection | PostUpdateNode should not equal its pre-update node. |
2434
postHasUniquePre
2535
uniquePostUpdate
2636
| aliasing.cpp:70:11:70:11 | VariableAddress indirection | Node has multiple PostUpdateNodes. |
@@ -41,6 +51,16 @@ postIsInSameCallable
4151
reverseRead
4252
argHasPostUpdate
4353
postWithInFlow
54+
| A.cpp:98:12:98:18 | new indirection | PostUpdateNode should not be the target of local flow. |
55+
| B.cpp:6:15:6:24 | new indirection | PostUpdateNode should not be the target of local flow. |
56+
| B.cpp:15:15:15:27 | new indirection | PostUpdateNode should not be the target of local flow. |
57+
| C.cpp:22:12:22:21 | new indirection | PostUpdateNode should not be the target of local flow. |
58+
| C.cpp:24:16:24:25 | new indirection | PostUpdateNode should not be the target of local flow. |
59+
| D.cpp:28:15:28:24 | new indirection | PostUpdateNode should not be the target of local flow. |
60+
| D.cpp:35:15:35:24 | new indirection | PostUpdateNode should not be the target of local flow. |
61+
| D.cpp:42:15:42:24 | new indirection | PostUpdateNode should not be the target of local flow. |
62+
| D.cpp:49:15:49:24 | new indirection | PostUpdateNode should not be the target of local flow. |
63+
| D.cpp:56:15:56:24 | new indirection | PostUpdateNode should not be the target of local flow. |
4464
| realistic.cpp:54:16:54:47 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
4565
| realistic.cpp:60:16:60:18 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
4666
viableImplInCallContextTooLarge

cpp/ql/test/library-tests/dataflow/taint-tests/arrayassignment.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ void test_myint_method_assignment()
6464
mi.get() = source();
6565

6666
sink(mi); // $ MISSING: ast,ir
67-
sink(mi.get()); // $ ast MISSING: ir
67+
sink(mi.get()); // $ ast,ir
6868
}
6969

7070
void test_myint_overloaded_assignment()
@@ -107,7 +107,7 @@ void test_myarray_method_assignment()
107107

108108
ma.get(0) = source();
109109

110-
sink(ma.get(0)); // $ MISSING: ast,ir
110+
sink(ma.get(0)); // $ ir MISSING: ast
111111
}
112112

113113
void test_myarray_overloaded_assignment()

cpp/ql/test/library-tests/syntax-zoo/dataflow-ir-consistency.expected

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,11 @@ compatibleTypesReflexive
192192
unreachableNodeCCtx
193193
localCallNodes
194194
postIsNotPre
195+
| condition_decls.cpp:3:13:3:22 | new indirection | PostUpdateNode should not equal its pre-update node. |
196+
| defdestructordeleteexpr.cpp:4:9:4:15 | new indirection | PostUpdateNode should not equal its pre-update node. |
197+
| deleteexpr.cpp:7:9:7:15 | new indirection | PostUpdateNode should not equal its pre-update node. |
198+
| ir.cpp:943:3:943:11 | new indirection | PostUpdateNode should not equal its pre-update node. |
199+
| ir.cpp:947:3:947:25 | new indirection | PostUpdateNode should not equal its pre-update node. |
195200
postHasUniquePre
196201
uniquePostUpdate
197202
| cpp11.cpp:82:17:82:17 | this indirection | Node has multiple PostUpdateNodes. |
@@ -215,14 +220,19 @@ postIsInSameCallable
215220
reverseRead
216221
argHasPostUpdate
217222
postWithInFlow
223+
| condition_decls.cpp:3:13:3:22 | new indirection | PostUpdateNode should not be the target of local flow. |
218224
| cpp11.cpp:77:19:77:21 | call to Val | PostUpdateNode should not be the target of local flow. |
219225
| cpp11.cpp:82:11:82:14 | call to Val | PostUpdateNode should not be the target of local flow. |
220226
| cpp11.cpp:82:45:82:48 | call to Val | PostUpdateNode should not be the target of local flow. |
221227
| cpp11.cpp:82:51:82:51 | call to Val | PostUpdateNode should not be the target of local flow. |
228+
| defdestructordeleteexpr.cpp:4:9:4:15 | new indirection | PostUpdateNode should not be the target of local flow. |
229+
| deleteexpr.cpp:7:9:7:15 | new indirection | PostUpdateNode should not be the target of local flow. |
222230
| ir.cpp:809:7:809:13 | call to Base | PostUpdateNode should not be the target of local flow. |
223231
| ir.cpp:810:7:810:26 | call to Base | PostUpdateNode should not be the target of local flow. |
224232
| ir.cpp:823:7:823:13 | call to Base | PostUpdateNode should not be the target of local flow. |
225233
| ir.cpp:824:7:824:26 | call to Base | PostUpdateNode should not be the target of local flow. |
234+
| ir.cpp:943:3:943:11 | new indirection | PostUpdateNode should not be the target of local flow. |
235+
| ir.cpp:947:3:947:25 | new indirection | PostUpdateNode should not be the target of local flow. |
226236
| try_catch.cpp:7:8:7:8 | call to exception | PostUpdateNode should not be the target of local flow. |
227237
viableImplInCallContextTooLarge
228238
uniqueParameterNodeAtPosition

0 commit comments

Comments
 (0)