Skip to content

Commit 62e2ffe

Browse files
committed
C++: Make PartialDefinitionNode private and add/update comments based on review comments
1 parent f02feac commit 62e2ffe

File tree

2 files changed

+24
-10
lines changed

2 files changed

+24
-10
lines changed

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ abstract class PostUpdateNode extends InstructionNode {
251251
* setY(&x); // a partial definition of the object `x`.
252252
* ```
253253
*/
254-
abstract class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { }
254+
abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { }
255255

256256
private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
257257
override ChiInstruction instr;
@@ -264,7 +264,7 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
264264
}
265265

266266
// There might be multiple `ChiInstructions` that has a particular instruction as
267-
// the total operand - so this definition give consistency errors in
267+
// the total operand - so this definition gives consistency errors in
268268
// DataFlowImplConsistency::Consistency. However, it's not clear what (if any) implications
269269
// this consistency failure has.
270270
override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() }
@@ -430,9 +430,23 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
430430
// for now.
431431
iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom
432432
or
433+
// The next two rules allow flow from partial definitions in setters to succeeding loads in the caller.
434+
// First, we add flow from write side-effects to non-conflated chi instructions through their
435+
// partial operands. Consider the following example:
436+
// ```
437+
// void setX(Point* p, int new_x) {
438+
// p->x = new_x;
439+
// }
440+
// ...
441+
// setX(&p, taint());
442+
// ```
443+
// Here, a `WriteSideEffectInstruction` will provide a new definition for `p->x` after the call to
444+
// `setX`, which will be melded into `p` through a chi instruction.
433445
iTo.getAnOperand().(ChiPartialOperand).getDef() = iFrom.(WriteSideEffectInstruction) and
434446
not iTo.isResultConflated()
435447
or
448+
// Next, we add flow from non-conflated chi instructions to loads (even when they are not precise).
449+
// This ensures that loads of `p->x` gets data flow from the `WriteSideEffectInstruction` above.
436450
exists(ChiInstruction chi | iFrom = chi |
437451
not chi.isResultConflated() and
438452
iTo.(LoadInstruction).getSourceValueOperand().getAnyDef() = chi

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,14 @@ void class_field_test() {
8585

8686
mc1.myMethod();
8787

88-
sink(mc1.a); // [FALSE POSITIVE]
89-
sink(mc1.b); // tainted
90-
sink(mc1.c); // tainted
91-
sink(mc1.d); // tainted
92-
sink(mc2.a); // [FALSE POSITIVE]
93-
sink(mc2.b); // tainted
94-
sink(mc2.c); // tainted
95-
sink(mc2.d); // [FALSE POSITIVE]
88+
sink(mc1.a);
89+
sink(mc1.b); // tainted [NOT DETECTED with IR]
90+
sink(mc1.c); // tainted [NOT DETECTED with IR]
91+
sink(mc1.d); // tainted [NOT DETECTED with IR]
92+
sink(mc2.a);
93+
sink(mc2.b); // tainted [NOT DETECTED with IR]
94+
sink(mc2.c); // tainted [NOT DETECTED with IR]
95+
sink(mc2.d);
9696
}
9797

9898
// --- arrays ---

0 commit comments

Comments
 (0)