Skip to content

Commit 439d3d2

Browse files
committed
C++: Add tests with higher level of indirection.
1 parent 0729c60 commit 439d3d2

File tree

4 files changed

+138
-0
lines changed

4 files changed

+138
-0
lines changed

cpp/ql/test/library-tests/dataflow/dataflow-tests/TestBase.qll

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,53 @@ module IRTest {
4949
import semmle.code.cpp.ir.dataflow.DataFlow
5050
private import semmle.code.cpp.ir.IR
5151
private import semmle.code.cpp.controlflow.IRGuards
52+
private import semmle.code.cpp.models.interfaces.DataFlow
53+
54+
boolean isOne(string s) {
55+
s = "1" and result = true
56+
or
57+
s = "0" and result = false
58+
}
59+
60+
/**
61+
* A model of a test function called `strdup_ptr_xyz` where `x, y, z in {0, 1}`.
62+
* `x` is 1 if there's flow from the argument to the function return,
63+
* `y` is 1 if there's flow from the first indirection of the argument to
64+
* the first indirection of the function return, and
65+
* `z` is 1 if there's flow from the second indirection of the argument to
66+
* the second indirection of the function return.
67+
*/
68+
class StrDupPtr extends DataFlowFunction {
69+
boolean argToReturnFlow;
70+
boolean argIndToReturnInd;
71+
boolean argIndInToReturnIndInd;
72+
73+
StrDupPtr() {
74+
exists(string r |
75+
r = "strdup_ptr_([01])([01])([01])" and
76+
argToReturnFlow = isOne(this.getName().regexpCapture(r, 1)) and
77+
argIndToReturnInd = isOne(this.getName().regexpCapture(r, 2)) and
78+
argIndInToReturnIndInd = isOne(this.getName().regexpCapture(r, 3))
79+
)
80+
}
81+
82+
/**
83+
* Flow from `**ptr` to `**return`
84+
*/
85+
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
86+
argToReturnFlow = true and
87+
input.isParameter(0) and
88+
output.isReturnValue()
89+
or
90+
argIndToReturnInd = true and
91+
input.isParameterDeref(0, 1) and
92+
output.isReturnValueDeref(1)
93+
or
94+
argIndInToReturnIndInd = true and
95+
input.isParameterDeref(0, 2) and
96+
output.isReturnValueDeref(2)
97+
}
98+
}
5299

53100
/**
54101
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ postIsInSameCallable
2424
reverseRead
2525
argHasPostUpdate
2626
| flowOut.cpp:55:14:55:16 | * ... | ArgumentNode is missing PostUpdateNode. |
27+
| flowOut.cpp:185:8:185:9 | * ... | ArgumentNode is missing PostUpdateNode. |
2728
| lambdas.cpp:18:7:18:7 | a | ArgumentNode is missing PostUpdateNode. |
2829
| lambdas.cpp:25:2:25:2 | b | ArgumentNode is missing PostUpdateNode. |
2930
| lambdas.cpp:32:2:32:2 | c | ArgumentNode is missing PostUpdateNode. |
@@ -64,6 +65,8 @@ postWithInFlow
6465
| flowOut.cpp:90:3:90:4 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
6566
| flowOut.cpp:90:4:90:4 | q [inner post update] | PostUpdateNode should not be the target of local flow. |
6667
| flowOut.cpp:101:14:101:14 | p [inner post update] | PostUpdateNode should not be the target of local flow. |
68+
| flowOut.cpp:168:3:168:10 | * ... [post update] | PostUpdateNode should not be the target of local flow. |
69+
| flowOut.cpp:168:4:168:10 | toTaint [inner post update] | PostUpdateNode should not be the target of local flow. |
6770
| globals.cpp:13:5:13:19 | flowTestGlobal1 [post update] | PostUpdateNode should not be the target of local flow. |
6871
| globals.cpp:23:5:23:19 | flowTestGlobal2 [post update] | PostUpdateNode should not be the target of local flow. |
6972
| lambdas.cpp:23:3:23:14 | v [post update] | PostUpdateNode should not be the target of local flow. |

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

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,4 +115,89 @@ void modify_copy_via_memcpy(char* p) { // $ ast-def=p
115115
void test_modify_copy_via_memcpy(char* p) { // $ ast-def=p
116116
modify_copy_via_memcpy(p);
117117
sink(*p); // clean
118+
}
119+
120+
// These functions from any real database. We add a dataflow model of
121+
// them as part of dataflow library testing.
122+
// `r = strdup_ptr_001`(p) has flow from **p to **r
123+
// `r = strdup_ptr_011`(p) has flow from *p to *r, and **p to **r
124+
// `r = strdup_ptr_111`(p) has flow from p to r, *p to *r, **p to **r
125+
char** strdup_ptr_001(const char** p);
126+
char** strdup_ptr_011(const char** p);
127+
char** strdup_ptr_111(const char** p);
128+
129+
void source_ref_ref(char** toTaint) { // $ ast-def=toTaint ir-def=*toTaint ir-def=**toTaint
130+
// source -> **toTaint
131+
**toTaint = source(true);
132+
}
133+
134+
// This function copies the value of **p into a new location **p2 and then
135+
// taints **p. Thus, **p does not contain tainted data after returning from
136+
// this function.
137+
void modify_copy_via_strdup_ptr_001(char** p) { // $ ast-def=p
138+
// **p -> **p2
139+
char** p2 = strdup_ptr_001(p);
140+
// source -> **p2
141+
source_ref_ref(p2);
142+
}
143+
144+
void test_modify_copy_via_strdup_001(char** p) { // $ ast-def=p
145+
modify_copy_via_strdup_ptr_001(p);
146+
sink(**p); // clean
147+
}
148+
149+
// This function copies the value of *p into a new location *p2 and then
150+
// taints **p2. Thus, **p contains tainted data after returning from this
151+
// function.
152+
void modify_copy_via_strdup_ptr_011(char** p) { // $ ast-def=p
153+
// **p -> **p2 and *p -> *p2
154+
char** p2 = strdup_ptr_011(p);
155+
// source -> **p2
156+
source_ref_ref(p2);
157+
}
158+
159+
void test_modify_copy_via_strdup_011(char** p) { // $ ast-def=p
160+
modify_copy_via_strdup_ptr_011(p);
161+
sink(**p); // $ ir MISSING: ast
162+
}
163+
164+
char* source(int);
165+
166+
void source_ref_2(char** toTaint) { // $ ast-def=toTaint ir-def=*toTaint ir-def=**toTaint
167+
// source -> *toTaint
168+
*toTaint = source(42);
169+
}
170+
171+
// This function copies the value of p into a new location p2 and then
172+
// taints *p2. Thus, *p contains tainted data after returning from this
173+
// function.
174+
void modify_copy_via_strdup_ptr_111_taint_ind(char** p) { // $ ast-def=p
175+
// **p -> **p2, *p -> *p2, and p -> p2
176+
char** p2 = strdup_ptr_111(p);
177+
// source -> *p2
178+
source_ref_2(p2);
179+
}
180+
181+
void sink(char*);
182+
183+
void test_modify_copy_via_strdup_111_taint_ind(char** p) { // $ ast-def=p
184+
modify_copy_via_strdup_ptr_111_taint_ind(p);
185+
sink(*p); // $ ir MISSING: ast
186+
}
187+
188+
// This function copies the value of p into a new location p2 and then
189+
// taints **p2. Thus, **p contains tainted data after returning from this
190+
// function.
191+
void modify_copy_via_strdup_ptr_111_taint_ind_ind(char** p) { // $ ast-def=p
192+
// **p -> **p2, *p -> *p2, and p -> p2
193+
char** p2 = strdup_ptr_111(p);
194+
// source -> **p2
195+
source_ref_ref(p2);
196+
}
197+
198+
void sink(char*);
199+
200+
void test_modify_copy_via_strdup_111_taint_ind_ind(char** p) { // $ ast-def=p
201+
modify_copy_via_strdup_ptr_111_taint_ind_ind(p);
202+
sink(**p); // $ ir MISSING: ast
118203
}

cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ irFlow
176176
| flowOut.cpp:5:16:5:21 | call to source | flowOut.cpp:61:8:61:11 | access to array |
177177
| flowOut.cpp:84:18:84:23 | call to source | flowOut.cpp:85:8:85:9 | * ... |
178178
| flowOut.cpp:90:8:90:13 | call to source | flowOut.cpp:102:8:102:9 | * ... |
179+
| flowOut.cpp:131:15:131:20 | call to source | flowOut.cpp:161:8:161:10 | * ... |
180+
| flowOut.cpp:131:15:131:20 | call to source | flowOut.cpp:202:8:202:10 | * ... |
181+
| flowOut.cpp:168:14:168:19 | call to source | flowOut.cpp:185:8:185:9 | * ... |
179182
| globals.cpp:5:17:5:22 | call to source | globals.cpp:6:10:6:14 | local |
180183
| globals.cpp:13:23:13:28 | call to source | globals.cpp:12:10:12:24 | flowTestGlobal1 |
181184
| globals.cpp:23:23:23:28 | call to source | globals.cpp:19:10:19:24 | flowTestGlobal2 |

0 commit comments

Comments
 (0)