Skip to content

Commit 41e46f6

Browse files
author
Robert Marsh
authored
Merge pull request #1584 from geoffw0/swap
CPP: Model std::swap
2 parents e1454ab + cd449e1 commit 41e46f6

File tree

8 files changed

+66
-0
lines changed

8 files changed

+66
-0
lines changed

change-notes/1.22/analysis-cpp.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@
2323
- The predicate `TypeMention.toString()` has been simplified to always return the string "`type mention`". This may improve performance when using `Element.toString()` or its descendants.
2424
- The `semmle.code.cpp.security.TaintTracking` library now considers a pointer difference calculation as blocking taint flow.
2525
- Fixed the `LocalScopeVariableReachability.qll` library's handling of loops with an entry condition is both always true upon first entry, and where there is more than one control flow path through the loop condition. This change increases the accuracy of the `LocalScopeVariableReachability.qll` library and queries which depend on it.
26+
- The `semmle.code.cpp.models` library now models data flow through `std::swap`.

cpp/ql/src/semmle/code/cpp/models/Models.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ private import implementations.Pure
66
private import implementations.Strcat
77
private import implementations.Strcpy
88
private import implementations.Strftime
9+
private import implementations.Swap
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import semmle.code.cpp.models.interfaces.DataFlow
2+
import semmle.code.cpp.models.interfaces.Taint
3+
4+
/**
5+
* The standard function `swap`.
6+
*/
7+
class Swap extends DataFlowFunction {
8+
Swap() {
9+
this.hasQualifiedName("std", "swap")
10+
}
11+
12+
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
13+
(
14+
input.isInParameterPointer(0) and
15+
output.isOutParameterPointer(1)
16+
)
17+
or
18+
(
19+
input.isInParameterPointer(1) and
20+
output.isOutParameterPointer(0)
21+
)
22+
}
23+
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,17 @@
161161
| taint.cpp:194:10:194:10 | x | taint.cpp:194:9:194:10 | & ... | TAINT |
162162
| taint.cpp:194:13:194:18 | source | taint.cpp:194:9:194:10 | ref arg & ... | TAINT |
163163
| taint.cpp:194:21:194:31 | sizeof(int) | taint.cpp:194:9:194:10 | ref arg & ... | TAINT |
164+
| taint.cpp:207:6:207:11 | call to source | taint.cpp:207:2:207:13 | ... = ... | |
165+
| taint.cpp:207:6:207:11 | call to source | taint.cpp:210:7:210:7 | x | |
166+
| taint.cpp:207:6:207:11 | call to source | taint.cpp:213:12:213:12 | x | |
167+
| taint.cpp:207:6:207:11 | call to source | taint.cpp:215:7:215:7 | x | |
168+
| taint.cpp:208:6:208:6 | 0 | taint.cpp:208:2:208:6 | ... = ... | |
169+
| taint.cpp:208:6:208:6 | 0 | taint.cpp:211:7:211:7 | y | |
170+
| taint.cpp:208:6:208:6 | 0 | taint.cpp:213:15:213:15 | y | |
171+
| taint.cpp:208:6:208:6 | 0 | taint.cpp:216:7:216:7 | y | |
172+
| taint.cpp:213:12:213:12 | ref arg x | taint.cpp:213:12:213:12 | x | |
173+
| taint.cpp:213:12:213:12 | ref arg x | taint.cpp:215:7:215:7 | x | |
174+
| taint.cpp:213:12:213:12 | x | taint.cpp:213:15:213:15 | ref arg y | |
175+
| taint.cpp:213:15:213:15 | ref arg y | taint.cpp:213:15:213:15 | y | |
176+
| taint.cpp:213:15:213:15 | ref arg y | taint.cpp:216:7:216:7 | y | |
177+
| taint.cpp:213:15:213:15 | y | taint.cpp:213:12:213:12 | ref arg x | |

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,3 +194,24 @@ void test_memcpy(int *source) {
194194
memcpy(&x, source, sizeof(int));
195195
sink(x);
196196
}
197+
198+
// --- swap ---
199+
200+
namespace std {
201+
template<class T> constexpr void swap(T& a, T& b);
202+
}
203+
204+
void test_swap() {
205+
int x, y;
206+
207+
x = source();
208+
y = 0;
209+
210+
sink(x); // tainted
211+
sink(y);
212+
213+
std::swap(x, y);
214+
215+
sink(x); // [FALSE POSITIVE]
216+
sink(y); // tainted
217+
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,6 @@
1414
| taint.cpp:181:8:181:9 | * ... | taint.cpp:185:11:185:16 | call to source |
1515
| taint.cpp:195:7:195:7 | x | taint.cpp:192:23:192:28 | source |
1616
| taint.cpp:195:7:195:7 | x | taint.cpp:193:6:193:6 | x |
17+
| taint.cpp:210:7:210:7 | x | taint.cpp:207:6:207:11 | call to source |
18+
| taint.cpp:215:7:215:7 | x | taint.cpp:207:6:207:11 | call to source |
19+
| taint.cpp:216:7:216:7 | y | taint.cpp:207:6:207:11 | call to source |

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
| taint.cpp:185:11:185:16 | taint.cpp:181:8:181:9 | AST only |
88
| taint.cpp:192:23:192:28 | taint.cpp:195:7:195:7 | AST only |
99
| taint.cpp:193:6:193:6 | taint.cpp:195:7:195:7 | AST only |
10+
| taint.cpp:207:6:207:11 | taint.cpp:215:7:215:7 | AST only |
11+
| taint.cpp:207:6:207:11 | taint.cpp:216:7:216:7 | AST only |

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
| taint.cpp:151:7:151:12 | Call: call to select | taint.cpp:151:20:151:25 | Call: call to source |
88
| taint.cpp:167:8:167:13 | Call: call to source | taint.cpp:167:8:167:13 | Call: call to source |
99
| taint.cpp:168:8:168:14 | Load: tainted | taint.cpp:164:19:164:24 | Call: call to source |
10+
| taint.cpp:210:7:210:7 | Load: x | taint.cpp:207:6:207:11 | Call: call to source |

0 commit comments

Comments
 (0)