Skip to content

Commit b205d36

Browse files
committed
C++: Remove chi -> load rule from simpleLocalFlowStep and accept tests
1 parent 617ef32 commit b205d36

File tree

3 files changed

+18
-42
lines changed

3 files changed

+18
-42
lines changed

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,6 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
229229
// Flow from an element to an array or union that contains it.
230230
i2.(ChiInstruction).getPartial() = i1 and
231231
not i2.isResultConflated() and
232-
not exists(PartialDefinitionNode n | n.asInstruction() = i2) and
233232
exists(Type t | i2.getResultLanguageType().hasType(t, false) |
234233
t instanceof Union
235234
or

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

Lines changed: 18 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,6 @@ abstract class PostUpdateNode extends InstructionNode {
239239
}
240240

241241
/**
242-
* INTERNAL: do not use.
243-
*
244242
* The base class for nodes that perform "partial definitions".
245243
*
246244
* In contrast to a normal "definition", which provides a new value for
@@ -253,7 +251,7 @@ abstract class PostUpdateNode extends InstructionNode {
253251
* setY(&x); // a partial definition of the object `x`.
254252
* ```
255253
*/
256-
abstract class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { }
254+
abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { }
257255

258256
private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
259257
override ChiInstruction instr;
@@ -272,17 +270,6 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
272270
override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() }
273271
}
274272

275-
private class FieldStoreWriteSideEffectNode extends PartialDefinitionNode {
276-
override ChiInstruction instr;
277-
278-
FieldStoreWriteSideEffectNode() {
279-
not instr.isResultConflated() and
280-
exists(WriteSideEffectInstruction sideEffect | instr.getPartial() = sideEffect)
281-
}
282-
283-
override Node getPreUpdateNode() { result.asInstruction() = instr.getTotal() }
284-
}
285-
286273
/**
287274
* Not every store instruction generates a chi instruction that we can attach a PostUpdateNode to.
288275
* For instance, an update to a field of a struct containing only one field. For these cases we
@@ -434,32 +421,6 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr
434421
*/
435422
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
436423
simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction())
437-
or
438-
// The next two rules allow flow from partial definitions in setters to succeeding loads in the caller.
439-
// First, we add flow from write side-effects to non-conflated chi instructions through their
440-
// partial operands. Consider the following example:
441-
// ```
442-
// void setX(Point* p, int new_x) {
443-
// p->x = new_x;
444-
// }
445-
// ...
446-
// setX(&p, taint());
447-
// ```
448-
// Here, a `WriteSideEffectInstruction` will provide a new definition for `p->x` after the call to
449-
// `setX`, which will be melded into `p` through a chi instruction.
450-
nodeTo instanceof FieldStoreWriteSideEffectNode and
451-
exists(ChiInstruction chi | chi = nodeTo.asInstruction() |
452-
chi.getPartialOperand().getDef() = nodeFrom.asInstruction().(WriteSideEffectInstruction) and
453-
not chi.isResultConflated()
454-
)
455-
or
456-
// Next, we add flow from non-conflated chi instructions to loads (even when they are not precise).
457-
// This ensures that loads of `p->x` gets data flow from the `WriteSideEffectInstruction` above.
458-
nodeFrom instanceof FieldStoreWriteSideEffectNode and
459-
exists(ChiInstruction chi | chi = nodeFrom.asInstruction() |
460-
not chi.isResultConflated() and
461-
nodeTo.asInstruction().(LoadInstruction).getSourceValueOperand().getAnyDef() = chi
462-
)
463424
}
464425

465426
pragma[noinline]
@@ -497,6 +458,23 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
497458
// for now.
498459
iTo.getAnOperand().(ChiTotalOperand).getDef() = iFrom
499460
or
461+
// Add flow from write side-effects to non-conflated chi instructions through their
462+
// partial operands. From there, a `readStep` will find subsequent reads of that field.
463+
// Consider the following example:
464+
// ```
465+
// void setX(Point* p, int new_x) {
466+
// p->x = new_x;
467+
// }
468+
// ...
469+
// setX(&p, taint());
470+
// ```
471+
// Here, a `WriteSideEffectInstruction` will provide a new definition for `p->x` after the call to
472+
// `setX`, which will be melded into `p` through a chi instruction.
473+
exists(ChiInstruction chi | chi = iTo |
474+
chi.getPartialOperand().getDef() = iFrom.(WriteSideEffectInstruction) and
475+
not chi.isResultConflated()
476+
)
477+
or
500478
// Flow from stores to structs with a single field to a load of that field.
501479
iTo.(LoadInstruction).getSourceValueOperand().getAnyDef() = iFrom and
502480
exists(int size, Type type |

cpp/ql/test/library-tests/dataflow/dataflow-tests/dataflow-ir-consistency.expected

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ postIsNotPre
3131
postHasUniquePre
3232
uniquePostUpdate
3333
| ref.cpp:83:5:83:17 | Chi | Node has multiple PostUpdateNodes. |
34-
| ref.cpp:100:34:100:36 | InitializeIndirection | Node has multiple PostUpdateNodes. |
3534
| ref.cpp:109:5:109:22 | Chi | Node has multiple PostUpdateNodes. |
3635
postIsInSameCallable
3736
reverseRead

0 commit comments

Comments
 (0)