@@ -199,18 +199,19 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
199199 // Flow through pointer dereference
200200 i2 .( LoadInstruction ) .getSourceAddress ( ) = i1
201201 or
202- // Flow through partial reads of arrays, unions, and pointer parameters
203- // TODO: `UnknownType` includes *all* pointer parameters. We only want
204- // array-like pointer parameters
205- i2 .( LoadInstruction ) .getSourceValueOperand ( ) .getAnyDef ( ) = i1 and
206- not i1 .isResultConflated ( ) and
202+ // Unary instructions tend to preserve enough information in practice that we
203+ // want taint to flow through.
204+ // The exception is `FieldAddressInstruction`. Together with the rule for
205+ // `LoadInstruction` above and for `ChiInstruction` below, flow through
206+ // `FieldAddressInstruction` could cause flow into one field to come out an
207+ // unrelated field. This would happen across function boundaries, where the IR
208+ // would not be able to match loads to stores.
209+ i2 .( UnaryInstruction ) .getUnary ( ) = i1 and
207210 (
208- i1 .getResultType ( ) instanceof ArrayType or
209- i1 .getResultType ( ) instanceof UnknownType or
210- i1 .getResultType ( ) instanceof Union
211- )
212- or
213- i2 .( UnaryInstruction ) .getUnary ( ) = i1
211+ not i2 instanceof FieldAddressInstruction
212+ or
213+ i2 .( FieldAddressInstruction ) .getField ( ) .getDeclaringType ( ) instanceof Union
214+ )
214215 or
215216 // Flow out of definition-by-reference
216217 i2 .( ChiInstruction ) .getPartial ( ) = i1 .( WriteSideEffectInstruction ) and
@@ -224,7 +225,7 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
224225 or
225226 t instanceof ArrayType
226227 or
227- // Buffers or unknown size
228+ // Buffers of unknown size
228229 t instanceof UnknownType
229230 )
230231 or
0 commit comments