Skip to content

Commit 28fa266

Browse files
author
Robert Marsh
committed
C++: output iterator flow with user-defined operators
1 parent 6552499 commit 28fa266

File tree

7 files changed

+200
-51
lines changed

7 files changed

+200
-51
lines changed

cpp/ql/src/semmle/code/cpp/dataflow/internal/AddressFlow.qll

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,17 @@ private predicate lvalueToLvalueStep(Expr lvalueIn, Expr lvalueOut) {
5252
or
5353
// C++ only
5454
lvalueIn = lvalueOut.(Assignment).getLValue().getFullyConverted()
55+
or
56+
// C++ only
57+
exists(Call c |
58+
lvalueOut = c and
59+
c.getTarget().hasName(["operator*", "operator++"]) and
60+
(
61+
c.getQualifier() = lvalueIn or
62+
not c.getTarget() instanceof MemberFunction and
63+
c.getArgument(0) = lvalueIn
64+
)
65+
)
5566
}
5667

5768
private predicate pointerToLvalueStep(Expr pointerIn, Expr lvalueOut) {
@@ -92,6 +103,17 @@ private predicate pointerToPointerStep(Expr pointerIn, Expr pointerOut) {
92103

93104
private predicate lvalueToReferenceStep(Expr lvalueIn, Expr referenceOut) {
94105
lvalueIn.getConversion() = referenceOut.(ReferenceToExpr)
106+
or
107+
// C++ only
108+
exists(Call c |
109+
referenceOut = c and
110+
c.getTarget().hasName(["operator*", "operator++"]) and
111+
(
112+
c.getQualifier() = lvalueIn or
113+
not c.getTarget() instanceof MemberFunction and
114+
c.getArgument(0) = lvalueIn
115+
)
116+
)
95117
}
96118

97119
private predicate referenceToLvalueStep(Expr referenceIn, Expr lvalueOut) {

cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,23 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
585585
nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr() = call and
586586
nodeTo.asDefiningArgument() = call.getQualifier()
587587
)
588+
or
589+
// Iterators that have a user-defined `operator=`. Take flow from the RHS to
590+
// the post-update node for the iterator.
591+
// The built-in `=` case is handled by FlowVar, other user-defined `operator=`
592+
// will be handled by interprocedural flow.
593+
exists(IteratorPartialDefinitionNode postUpdate, Call opEquals |
594+
postUpdate = nodeTo and
595+
opEquals.getTarget().hasName("operator=") and
596+
if opEquals.getTarget() instanceof MemberFunction
597+
then
598+
opEquals.getQualifier() = postUpdate.getPreUpdateNode().asExpr() and
599+
opEquals.getArgument(0) = nodeFrom.asExpr()
600+
else (
601+
opEquals.getArgument(0) = postUpdate.getPreUpdateNode().asExpr() and
602+
opEquals.getArgument(1) = nodeFrom.asExpr()
603+
)
604+
)
588605
}
589606

590607
/**

cpp/ql/src/semmle/code/cpp/dataflow/internal/FlowVar.qll

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,9 @@ private module PartialDefinitions {
163163
valueToUpdate(convertedInner, this.getFullyConverted(), node) and
164164
innerDefinedExpr = convertedInner.getUnconverted() and
165165
(
166-
innerDefinedExpr.(Call).getQualifier() = getAnIteratorAccess(collection)
166+
innerDefinedExpr.(Call).getQualifier() = getCrementedExpr*(getAnIteratorAccess(collection))
167167
or
168-
innerDefinedExpr.(Call).getQualifier() = collection.getAnAccess() and
168+
innerDefinedExpr.(Call).getQualifier() = getCrementedExpr*(collection.getAnAccess()) and
169169
collection instanceof IteratorParameter
170170
) and
171171
innerDefinedExpr.(Call).getTarget() instanceof IteratorPointerDereferenceMemberOperator
@@ -823,10 +823,12 @@ module FlowVar_internal {
823823
def.getAnUltimateDefiningValue(iterator) = c and
824824
result = def.getAUse(iterator)
825825
)
826-
or
826+
}
827+
828+
Expr getCrementedExpr(Expr e) {
827829
exists(Call crement |
828830
crement = result and
829-
[crement.getQualifier(), crement.getArgument(0)] = getAnIteratorAccess(collection) and
831+
[crement.getQualifier(), crement.getArgument(0)] = e and
830832
crement.getTarget().getName() = ["operator++", "operator--"]
831833
)
832834
}

cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected

Lines changed: 130 additions & 47 deletions
Large diffs are not rendered by default.

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,10 @@
250250
| smart_pointer.cpp:13:10:13:10 | p | smart_pointer.cpp:11:52:11:57 | call to source |
251251
| smart_pointer.cpp:24:10:24:10 | call to operator* | smart_pointer.cpp:23:52:23:57 | call to source |
252252
| smart_pointer.cpp:25:10:25:10 | p | smart_pointer.cpp:23:52:23:57 | call to source |
253+
| smart_pointer.cpp:38:10:38:10 | p | smart_pointer.cpp:37:10:37:15 | call to source |
254+
| smart_pointer.cpp:39:10:39:10 | call to operator* | smart_pointer.cpp:37:10:37:15 | call to source |
255+
| smart_pointer.cpp:46:10:46:10 | p | smart_pointer.cpp:45:10:45:15 | call to source |
256+
| smart_pointer.cpp:47:10:47:10 | call to operator* | smart_pointer.cpp:45:10:45:15 | call to source |
253257
| smart_pointer.cpp:52:12:52:14 | call to get | smart_pointer.cpp:51:52:51:57 | call to source |
254258
| smart_pointer.cpp:57:12:57:14 | call to get | smart_pointer.cpp:56:52:56:57 | call to source |
255259
| standalone_iterators.cpp:40:10:40:10 | call to operator* | standalone_iterators.cpp:39:45:39:51 | source1 |
@@ -258,6 +262,9 @@
258262
| standalone_iterators.cpp:46:10:46:10 | call to operator* | standalone_iterators.cpp:45:39:45:45 | source1 |
259263
| standalone_iterators.cpp:47:10:47:10 | call to operator* | standalone_iterators.cpp:45:39:45:45 | source1 |
260264
| standalone_iterators.cpp:48:10:48:10 | call to operator* | standalone_iterators.cpp:45:39:45:45 | source1 |
265+
| standalone_iterators.cpp:52:10:52:10 | call to operator* | standalone_iterators.cpp:51:37:51:43 | source1 |
266+
| standalone_iterators.cpp:53:10:53:10 | call to operator* | standalone_iterators.cpp:51:37:51:43 | source1 |
267+
| standalone_iterators.cpp:54:10:54:10 | call to operator* | standalone_iterators.cpp:51:37:51:43 | source1 |
261268
| string.cpp:29:7:29:7 | a | string.cpp:25:12:25:17 | call to source |
262269
| string.cpp:31:7:31:7 | c | string.cpp:27:16:27:21 | call to source |
263270
| string.cpp:33:9:33:13 | call to c_str | string.cpp:27:16:27:21 | call to source |
@@ -657,3 +664,5 @@
657664
| vector.cpp:409:7:409:9 | v13 | vector.cpp:408:11:408:16 | call to source |
658665
| vector.cpp:414:7:414:9 | v14 | vector.cpp:413:11:413:16 | call to source |
659666
| vector.cpp:422:8:422:10 | out | vector.cpp:417:33:417:45 | source_string |
667+
| vector.cpp:429:8:429:10 | out | vector.cpp:417:33:417:45 | source_string |
668+
| vector.cpp:436:8:436:10 | out | vector.cpp:435:11:435:16 | call to source |
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import TaintTestCommon
2+
3+
import DataFlow::PathGraph
4+
5+
from DataFlow::PathNode sink, DataFlow::PathNode source, TestAllocationConfig cfg
6+
where cfg.hasFlowPath(source, sink)
7+
select sink, source

cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,10 +200,17 @@
200200
| set.cpp:237:7:237:9 | set.cpp:236:37:236:42 | AST only |
201201
| smart_pointer.cpp:12:10:12:10 | smart_pointer.cpp:11:52:11:57 | AST only |
202202
| smart_pointer.cpp:24:10:24:10 | smart_pointer.cpp:23:52:23:57 | AST only |
203+
| smart_pointer.cpp:38:10:38:10 | smart_pointer.cpp:37:10:37:15 | AST only |
204+
| smart_pointer.cpp:39:10:39:10 | smart_pointer.cpp:37:10:37:15 | AST only |
205+
| smart_pointer.cpp:46:10:46:10 | smart_pointer.cpp:45:10:45:15 | AST only |
206+
| smart_pointer.cpp:47:10:47:10 | smart_pointer.cpp:45:10:45:15 | AST only |
203207
| standalone_iterators.cpp:41:10:41:10 | standalone_iterators.cpp:39:45:39:51 | AST only |
204208
| standalone_iterators.cpp:42:10:42:10 | standalone_iterators.cpp:39:45:39:51 | AST only |
205209
| standalone_iterators.cpp:47:10:47:10 | standalone_iterators.cpp:45:39:45:45 | AST only |
206210
| standalone_iterators.cpp:48:10:48:10 | standalone_iterators.cpp:45:39:45:45 | AST only |
211+
| standalone_iterators.cpp:52:10:52:10 | standalone_iterators.cpp:51:37:51:43 | AST only |
212+
| standalone_iterators.cpp:53:10:53:10 | standalone_iterators.cpp:51:37:51:43 | AST only |
213+
| standalone_iterators.cpp:54:10:54:10 | standalone_iterators.cpp:51:37:51:43 | AST only |
207214
| string.cpp:33:9:33:13 | string.cpp:27:16:27:21 | AST only |
208215
| string.cpp:39:13:39:17 | string.cpp:14:10:14:15 | AST only |
209216
| string.cpp:43:13:43:17 | string.cpp:14:10:14:15 | AST only |
@@ -383,3 +390,5 @@
383390
| vector.cpp:409:7:409:9 | vector.cpp:408:11:408:16 | AST only |
384391
| vector.cpp:414:7:414:9 | vector.cpp:413:11:413:16 | AST only |
385392
| vector.cpp:422:8:422:10 | vector.cpp:417:33:417:45 | AST only |
393+
| vector.cpp:429:8:429:10 | vector.cpp:417:33:417:45 | AST only |
394+
| vector.cpp:436:8:436:10 | vector.cpp:435:11:435:16 | AST only |

0 commit comments

Comments
 (0)