Skip to content

Commit 52d2beb

Browse files
committed
C++: Taint through most partial chi operands
This changes the flow to be taint rather than data flow, and it extends it to include chi instructions with unknown type as long as they're not for the `AliasedVirtualVariable`. We're losing three good test results because these tests are not affected by `DefaultTaintTracking.qll`. The taint step added here can later be ported to `TaintTrackingUtil.qll` to recover these results, but we probably want a better API than transitive-closure search through instructions before doing that.
1 parent 02cb8e9 commit 52d2beb

File tree

5 files changed

+22
-20
lines changed

5 files changed

+22
-20
lines changed

cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
149149
or
150150
i2.(UnaryInstruction).getUnary() = i1
151151
or
152+
i2.(ChiInstruction).getPartial() = i1 and
153+
not isChiForAllAliasedMemory(i2)
154+
or
152155
exists(BinaryInstruction bin |
153156
bin = i2 and
154157
predictableInstruction(i2.getAnOperand().getDef()) and
@@ -205,6 +208,19 @@ private predicate modelTaintToParameter(Function f, int parameterIn, int paramet
205208
)
206209
}
207210

211+
/**
212+
* Holds if `chi` is on the chain of chi-instructions for all aliased memory.
213+
* Taint shoud not pass through these instructions since they tend to mix up
214+
* unrelated objects.
215+
*/
216+
private predicate isChiForAllAliasedMemory(Instruction instr) {
217+
instr.(ChiInstruction).getTotal() instanceof AliasedDefinitionInstruction
218+
or
219+
isChiForAllAliasedMemory(instr.(ChiInstruction).getTotal())
220+
or
221+
isChiForAllAliasedMemory(instr.(PhiInstruction).getAnInput())
222+
}
223+
208224
private predicate modelTaintToReturnValue(Function f, int parameterIn) {
209225
// Taint flow from parameter to return value
210226
exists(FunctionInput modelIn, FunctionOutput modelOut |

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

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -283,18 +283,10 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
283283
// By allowing flow through the total operand, we ensure that flow is not lost
284284
// due to shortcomings of the alias analysis. We may get false flow in cases
285285
// where the data is indeed overwritten.
286+
//
287+
// Flow through the partial operand belongs in the taint-tracking libraries
288+
// for now.
286289
iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom
287-
or
288-
// Flow through the partial operand must be restricted a bit more. For
289-
// soundness, the IR has to assume that every write to an unknown address can
290-
// affect every escaped variable, and this assumption shows up as data flowing
291-
// through partial chi operands. The chi instructions for all escaped data can
292-
// be recognized by having unknown types. For all other chi instructions, flow
293-
// through partial operands is more likely to be real.
294-
exists(ChiInstruction chi | iTo = chi |
295-
iFrom = chi.getPartial() and
296-
not chi.getResultIRType() instanceof IRUnknownType
297-
)
298290
}
299291

300292
/**

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ void array_test(int i) {
107107
arr3[5] = 0;
108108

109109
sink(arr1[5]); // tainted
110-
sink(arr1[i]); // tainted [NOT DETECTED with AST]
111-
sink(arr2[5]); // tainted [NOT DETECTED with AST]
112-
sink(arr2[i]); // tainted [NOT DETECTED with AST]
110+
sink(arr1[i]); // tainted [NOT DETECTED]
111+
sink(arr2[5]); // tainted [NOT DETECTED]
112+
sink(arr2[i]); // tainted [NOT DETECTED]
113113
sink(arr3[5]);
114114
sink(arr3[i]);
115115
}

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,6 @@
1717
| taint.cpp:93:11:93:11 | taint.cpp:71:22:71:27 | AST only |
1818
| taint.cpp:94:11:94:11 | taint.cpp:72:7:72:12 | AST only |
1919
| taint.cpp:109:7:109:13 | taint.cpp:105:12:105:17 | IR only |
20-
| taint.cpp:110:7:110:13 | taint.cpp:105:12:105:17 | IR only |
21-
| taint.cpp:111:7:111:13 | taint.cpp:106:12:106:17 | IR only |
22-
| taint.cpp:112:7:112:13 | taint.cpp:106:12:106:17 | IR only |
2320
| taint.cpp:130:7:130:9 | taint.cpp:127:8:127:13 | IR only |
2421
| taint.cpp:137:7:137:9 | taint.cpp:120:11:120:16 | AST only |
2522
| taint.cpp:173:8:173:13 | taint.cpp:164:19:164:24 | AST only |

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
| taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source |
33
| taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source |
44
| taint.cpp:109:7:109:13 | access to array | taint.cpp:105:12:105:17 | call to source |
5-
| taint.cpp:110:7:110:13 | access to array | taint.cpp:105:12:105:17 | call to source |
6-
| taint.cpp:111:7:111:13 | access to array | taint.cpp:106:12:106:17 | call to source |
7-
| taint.cpp:112:7:112:13 | access to array | taint.cpp:106:12:106:17 | call to source |
85
| taint.cpp:129:7:129:9 | * ... | taint.cpp:120:11:120:16 | call to source |
96
| taint.cpp:130:7:130:9 | * ... | taint.cpp:127:8:127:13 | call to source |
107
| taint.cpp:134:7:134:9 | * ... | taint.cpp:120:11:120:16 | call to source |

0 commit comments

Comments
 (0)