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.
This commit is contained in:
Jonas Jensen
2020-04-07 15:47:49 +02:00
parent 8928091dfb
commit 39911af56b

View File

@@ -189,9 +189,22 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
or
i2.(UnaryInstruction).getUnary() = i1
or
i2.(ChiInstruction).getPartial() = i1 and
// Flow out of definition-by-reference
i2.(ChiInstruction).getPartial() = i1.(WriteSideEffectInstruction) and
not i2.isResultConflated()
or
// Flow from an element to an array or union that contains it.
i2.(ChiInstruction).getPartial() = i1 and
not i2.isResultConflated() and
exists(Type t | i2.getResultLanguageType().hasType(t, false) |
t instanceof Union
or
t instanceof ArrayType
or
// Buffers or unknown size
t instanceof UnknownType
)
or
exists(BinaryInstruction bin |
bin = i2 and
predictableInstruction(i2.getAnOperand().getDef()) and