Skip to content

Commit 39911af

Browse files
committed
C++: Avoid partial chi flow to struct/class
Flow through partial chi-instruction operands was introduced to make definition-by-reference work, but its implementation also allowed all other partial writes to propagate. In particular, tainting a field would taint the whole struct, which in turn led to taint propagating across unrelated fields of a struct. The security test `CWE-134/semmle/argv/argvLocal.c` shows that we also want to propagate taint from an array element to the whole array, and it also seems right to propagate taint from a union member to the whole union.
1 parent 8928091 commit 39911af

File tree

1 file changed

+14
-1
lines changed

1 file changed

+14
-1
lines changed

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

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,22 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
189189
or
190190
i2.(UnaryInstruction).getUnary() = i1
191191
or
192-
i2.(ChiInstruction).getPartial() = i1 and
192+
// Flow out of definition-by-reference
193+
i2.(ChiInstruction).getPartial() = i1.(WriteSideEffectInstruction) and
193194
not i2.isResultConflated()
194195
or
196+
// Flow from an element to an array or union that contains it.
197+
i2.(ChiInstruction).getPartial() = i1 and
198+
not i2.isResultConflated() and
199+
exists(Type t | i2.getResultLanguageType().hasType(t, false) |
200+
t instanceof Union
201+
or
202+
t instanceof ArrayType
203+
or
204+
// Buffers or unknown size
205+
t instanceof UnknownType
206+
)
207+
or
195208
exists(BinaryInstruction bin |
196209
bin = i2 and
197210
predictableInstruction(i2.getAnOperand().getDef()) and

0 commit comments

Comments
 (0)