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

Skip to content

Commit 6233722

Browse files
committed
C++: Better support for flow-through.
1 parent 7658df9 commit 6233722

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
@@ -595,10 +595,33 @@ predicate indirectReturnOutNodeInstruction0(
595595
instructionForfullyConvertedCall(instr, call)
596596
}
597597

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

621638
CallInstruction getCallInstruction() { result = call }
622639

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

626672
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
@@ -320,6 +320,11 @@ compatibleTypesReflexive
320320
unreachableNodeCCtx
321321
localCallNodes
322322
postIsNotPre
323+
| condition_decls.cpp:3:13:3:22 | new indirection | PostUpdateNode should not equal its pre-update node. |
324+
| defdestructordeleteexpr.cpp:4:9:4:15 | new indirection | PostUpdateNode should not equal its pre-update node. |
325+
| deleteexpr.cpp:7:9:7:15 | new indirection | PostUpdateNode should not equal its pre-update node. |
326+
| ir.cpp:943:3:943:11 | new indirection | PostUpdateNode should not equal its pre-update node. |
327+
| ir.cpp:947:3:947:25 | new indirection | PostUpdateNode should not equal its pre-update node. |
323328
postHasUniquePre
324329
uniquePostUpdate
325330
| cpp11.cpp:82:17:82:17 | this indirection | Node has multiple PostUpdateNodes. |
@@ -343,13 +348,18 @@ postIsInSameCallable
343348
reverseRead
344349
argHasPostUpdate
345350
postWithInFlow
351+
| condition_decls.cpp:3:13:3:22 | new indirection | PostUpdateNode should not be the target of local flow. |
346352
| cpp11.cpp:77:19:77:21 | call to Val | PostUpdateNode should not be the target of local flow. |
347353
| cpp11.cpp:82:11:82:14 | call to Val | PostUpdateNode should not be the target of local flow. |
348354
| cpp11.cpp:82:45:82:48 | call to Val | PostUpdateNode should not be the target of local flow. |
349355
| cpp11.cpp:82:51:82:51 | call to Val | PostUpdateNode should not be the target of local flow. |
356+
| defdestructordeleteexpr.cpp:4:9:4:15 | new indirection | PostUpdateNode should not be the target of local flow. |
357+
| deleteexpr.cpp:7:9:7:15 | new indirection | PostUpdateNode should not be the target of local flow. |
350358
| ir.cpp:809:7:809:13 | call to Base | PostUpdateNode should not be the target of local flow. |
351359
| ir.cpp:810:7:810:26 | call to Base | PostUpdateNode should not be the target of local flow. |
352360
| ir.cpp:823:7:823:13 | call to Base | PostUpdateNode should not be the target of local flow. |
353361
| ir.cpp:824:7:824:26 | call to Base | PostUpdateNode should not be the target of local flow. |
362+
| ir.cpp:943:3:943:11 | new indirection | PostUpdateNode should not be the target of local flow. |
363+
| ir.cpp:947:3:947:25 | new indirection | PostUpdateNode should not be the target of local flow. |
354364
| try_catch.cpp:7:8:7:8 | call to exception | PostUpdateNode should not be the target of local flow. |
355365
viableImplInCallContextTooLarge

0 commit comments

Comments
 (0)