Skip to content

Commit 69ce24d

Browse files
authored
Merge pull request #5035 from MathiasVP/implied-deref-flow
C++: Implied dataflow models
2 parents 65ea01e + 52e2a69 commit 69ce24d

File tree

5 files changed

+58
-27
lines changed

5 files changed

+58
-27
lines changed

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -920,6 +920,27 @@ private predicate modelFlow(Operand opFrom, Instruction iTo) {
920920
)
921921
)
922922
)
923+
or
924+
impliedModelFlow(opFrom, iTo)
925+
}
926+
927+
/**
928+
* When a `DataFlowFunction` specifies dataflow from a parameter `p` to the return value there should
929+
* also be dataflow from the parameter dereference (i.e., `*p`) to the return value dereference.
930+
*/
931+
private predicate impliedModelFlow(Operand opFrom, Instruction iTo) {
932+
exists(
933+
CallInstruction call, DataFlowFunction func, FunctionInput modelIn, FunctionOutput modelOut,
934+
int index
935+
|
936+
call.getStaticCallTarget() = func and
937+
func.hasDataFlow(modelIn, modelOut)
938+
|
939+
modelIn.isParameterOrQualifierAddress(index) and
940+
modelOut.isReturnValue() and
941+
opFrom = getSideEffectFor(call, index).(ReadSideEffectInstruction).getSideEffectOperand() and
942+
iTo = call // TODO: Add write side effects for return values
943+
)
923944
}
924945

925946
/**

cpp/ql/src/semmle/code/cpp/models/interfaces/FunctionInputsAndOutputs.qll

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,16 @@ class FunctionInput extends TFunctionInput {
108108
*/
109109
predicate isQualifierAddress() { none() }
110110

111+
/**
112+
* Holds if `i >= 0` and `isParameter(i)` holds for this value, or
113+
* if `i = -1` and `isQualifierAddress()` holds for this value.
114+
*/
115+
final predicate isParameterOrQualifierAddress(ParameterIndex i) {
116+
i >= 0 and this.isParameter(i)
117+
or
118+
i = -1 and this.isQualifierAddress()
119+
}
120+
111121
/**
112122
* Holds if this is the input value pointed to by the return value of a
113123
* function, if the function returns a pointer, or the input value referred
@@ -134,7 +144,7 @@ class FunctionInput extends TFunctionInput {
134144
predicate isReturnValueDeref() { none() }
135145

136146
/**
137-
* Holds if `i >= 0` and `isParameterDeref(i)` holds for this is value, or
147+
* Holds if `i >= 0` and `isParameterDeref(i)` holds for this value, or
138148
* if `i = -1` and `isQualifierObject()` holds for this value.
139149
*/
140150
final predicate isParameterDerefOrQualifierObject(ParameterIndex i) {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ class non_iterator {
3838

3939
void test_typedefs(int_iterator_by_typedefs source1) {
4040
sink(*source1); // $ ast,ir
41-
sink(*(source1++)); // $ ast MISSING: ir
41+
sink(*(source1++)); // $ ast,ir
4242
sink(*(++source1)); // $ ast MISSING: ir
4343
}
4444

4545
void test_trait(int_iterator_by_trait source1) {
4646
sink(*source1); // $ ast,ir
47-
sink(*(source1++)); // $ ast MISSING: ir
47+
sink(*(source1++)); // $ ast,ir
4848
sink(*(++source1)); // $ ast MISSING: ir
4949
}
5050

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,10 +415,10 @@ void test_string_iterators() {
415415
sink(*i9); // $ ast,ir
416416

417417
i10 = i2;
418-
sink(*(i10++)); // $ ast MISSING: ir
418+
sink(*(i10++)); // $ ast,ir
419419
sink(i10); // $ ast,ir
420420
i11 = i2;
421-
sink(*(i11--)); // $ ast MISSING: ir
421+
sink(*(i11--)); // $ ast,ir
422422
sink(i11); // $ ast,ir
423423
}
424424
}

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

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ void test_stringstream_int(int source)
7575
sink(ss1 << 1234);
7676
sink(ss2 << source); // $ ast MISSING: ir
7777
sink(ss1 >> v1);
78-
sink(ss2 >> v2); // $ ast MISSING: ir
78+
sink(ss2 >> v2); // $ ast,ir
7979

8080
sink(ss1);
8181
sink(ss2); // $ ast,ir
@@ -143,27 +143,27 @@ void test_stringstream_in()
143143
sink(ss2 << source()); // $ ast,ir
144144

145145
sink(ss1 >> s1);
146-
sink(ss2 >> s2); // $ ast MISSING: ir
147-
sink(ss2 >> s3 >> s4); // $ ast MISSING: ir
146+
sink(ss2 >> s2); // $ ast,ir
147+
sink(ss2 >> s3 >> s4); // $ ast,ir
148148
sink(s1);
149149
sink(s2); // $ ast,ir
150150
sink(s3); // $ ast,ir
151-
sink(s4); // $ ast MISSING: ir
151+
sink(s4); // $ ast,ir
152152

153153
sink(ss1 >> b1);
154-
sink(ss2 >> b2); // $ ast MISSING: ir
155-
sink(ss2 >> b3 >> b4); // $ ast MISSING: ir
154+
sink(ss2 >> b2); // $ ast,ir
155+
sink(ss2 >> b3 >> b4); // $ ast,ir
156156
sink(b1);
157157
sink(b2); // $ ast,ir
158158
sink(b3); // $ ast,ir
159-
sink(b4); // $ ast MISSING: ir
159+
sink(b4); // $ ast,ir
160160

161161
sink(ss1.read(b5, 100));
162-
sink(ss2.read(b6, 100)); // $ ast MISSING: ir
162+
sink(ss2.read(b6, 100)); // $ ast,ir
163163
sink(ss1.readsome(b7, 100));
164164
sink(ss2.readsome(b8, 100)); // (returns a length, not significantly tainted)
165165
sink(ss1.get(b9, 100));
166-
sink(ss2.get(b10, 100)); // $ ast MISSING: ir
166+
sink(ss2.get(b10, 100)); // $ ast,ir
167167
sink(b5);
168168
sink(b6); // $ ast,ir
169169
sink(b7);
@@ -176,7 +176,7 @@ void test_stringstream_in()
176176
sink(c3 = ss1.peek());
177177
sink(c4 = ss2.peek()); // $ ast,ir
178178
sink(ss1.get(c5));
179-
sink(ss2.get(c6)); // $ ast MISSING: ir
179+
sink(ss2.get(c6)); // $ ast,ir
180180
sink(c1);
181181
sink(c2); // $ ast,ir
182182
sink(c3);
@@ -212,44 +212,44 @@ void test_getline()
212212
std::string s1, s2, s3, s4, s5, s6, s7, s8;
213213

214214
sink(ss1.getline(b1, 1000));
215-
sink(ss2.getline(b2, 1000)); // $ ast MISSING: ir
216-
sink(ss2.getline(b3, 1000)); // $ ast MISSING: ir
215+
sink(ss2.getline(b2, 1000)); // $ ast,ir
216+
sink(ss2.getline(b3, 1000)); // $ ast,ir
217217
sink(ss1.getline(b3, 1000));
218218
sink(b1);
219219
sink(b2); // $ ast,ir
220220
sink(b3); // $ SPURIOUS: ast,ir
221221

222222
sink(ss1.getline(b4, 1000, ' '));
223-
sink(ss2.getline(b5, 1000, ' ')); // $ ast MISSING: ir
224-
sink(ss2.getline(b6, 1000, ' ')); // $ ast MISSING: ir
223+
sink(ss2.getline(b5, 1000, ' ')); // $ ast,ir
224+
sink(ss2.getline(b6, 1000, ' ')); // $ ast,ir
225225
sink(ss1.getline(b6, 1000, ' '));
226226
sink(b4);
227227
sink(b5); // $ ast,ir
228228
sink(b6); // $ SPURIOUS: ast,ir
229229

230-
sink(ss2.getline(b7, 1000).getline(b8, 1000)); // $ ast MISSING: ir
230+
sink(ss2.getline(b7, 1000).getline(b8, 1000)); // $ ast,ir
231231
sink(b7); // $ ast,ir
232232
sink(b8); // $ ast MISSING: ir
233233

234234
sink(getline(ss1, s1));
235-
sink(getline(ss2, s2)); // $ ast MISSING: ir
236-
sink(getline(ss2, s3)); // $ ast MISSING: ir
235+
sink(getline(ss2, s2)); // $ ast,ir
236+
sink(getline(ss2, s3)); // $ ast,ir
237237
sink(getline(ss1, s3));
238238
sink(s1);
239239
sink(s2); // $ ast,ir
240240
sink(s3); // $ SPURIOUS: ast,ir
241241

242242
sink(getline(ss1, s4, ' '));
243-
sink(getline(ss2, s5, ' ')); // $ ast MISSING: ir
244-
sink(getline(ss2, s6, ' ')); // $ ast MISSING: ir
243+
sink(getline(ss2, s5, ' ')); // $ ast,ir
244+
sink(getline(ss2, s6, ' ')); // $ ast,ir
245245
sink(getline(ss1, s6, ' '));
246246
sink(s4);
247247
sink(s5); // $ ast,ir
248248
sink(s6); // $ SPURIOUS: ast,ir
249249

250-
sink(getline(getline(ss2, s7), s8)); // $ ast MISSING: ir
250+
sink(getline(getline(ss2, s7), s8)); // $ ast,ir
251251
sink(s7); // $ ast,ir
252-
sink(s8); // $ ast MISSING: ir
252+
sink(s8); // $ ast,ir
253253
}
254254

255255
void test_chaining()
@@ -259,7 +259,7 @@ void test_chaining()
259259
char b1[1000] = {0};
260260
char b2[1000] = {0};
261261

262-
sink(ss1.get(b1, 100).unget().get(b2, 100)); // $ ast MISSING: ir
262+
sink(ss1.get(b1, 100).unget().get(b2, 100)); // $ ast,ir
263263
sink(b1); // $ ast,ir
264264
sink(b2); // $ ast MISSING: ir
265265

0 commit comments

Comments
 (0)