Skip to content

Commit ce34d91

Browse files
committed
C++: Add more QLDoc to StoreNode and LoadNode classes, and related predicates. I also simplified the code a bit by moving common implementations of predicates into shared super classes. Finally, I added a getLocation predicate to StoreNode to match the structure of the LoadNode class.
1 parent 3adc10f commit ce34d91

File tree

1 file changed

+58
-11
lines changed

1 file changed

+58
-11
lines changed

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

Lines changed: 58 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -462,20 +462,46 @@ private newtype TStoreChain =
462462
)
463463
}
464464

465+
/**
466+
* A `StoreChain` represents a series of field lookups that compute the destination of a store.
467+
* For example, given an assignment such as `a.b.c = x`, there are two `StoreChain`s:
468+
* One corresponding to the field `b`, and one corresponding to the field `c`. Here, `b` is the parent
469+
* `StoreChain` of `c`.
470+
*/
465471
private class StoreChain extends TStoreChain {
466472
string toString() { none() }
467473

468-
StoreChainConsCons getParent() { none() }
474+
/**
475+
* Gets the parent of this `StoreChain`, if any. For example, for the assignment
476+
* ```
477+
* a.b.c = x;
478+
* ```
479+
* the parent of `c` is `b`, and `b` has no parent.
480+
*/
481+
final StoreChainConsCons getParent() { result.getChild() = this }
469482

483+
/** Gets the child of this `StoreChain`, if any. */
470484
StoreChain getChild() { none() }
471485

486+
/**
487+
* Gets the instruction that receives flow from the outermost `StoreChain` of this chain (i.e.,
488+
* the `StoreChain` with no parent).
489+
*/
472490
StoreChainEndInstruction getEndInstruction() { none() }
473491

492+
/**
493+
* Gets the instruction that flows to the innermost `StoreChain` of this chain (i.e.,
494+
* the `StoreChain` with no child).
495+
*/
474496
Instruction getBeginInstruction() { none() }
475497

498+
/** Gets the `FieldAddressInstruction` of this `StoreChain` */
476499
FieldAddressInstruction getFieldInstruction() { none() }
477500

501+
/** Gets the `FieldAddressInstruction` of any `StoreChain` in this chain. */
478502
FieldAddressInstruction getAFieldInstruction() { none() }
503+
504+
final Location getLocation() { result = getFieldInstruction().getLocation() }
479505
}
480506

481507
private class StoreChainConsNil extends StoreChain, TStoreChainConsNil {
@@ -486,8 +512,6 @@ private class StoreChainConsNil extends StoreChain, TStoreChainConsNil {
486512

487513
override string toString() { result = fi.getField().toString() }
488514

489-
override StoreChainConsCons getParent() { result = TStoreChainConsCons(_, this) }
490-
491515
override StoreChainEndInstruction getEndInstruction() { result = end }
492516

493517
override Instruction getBeginInstruction() { result = end.getBeginInstruction() }
@@ -505,8 +529,6 @@ private class StoreChainConsCons extends StoreChain, TStoreChainConsCons {
505529

506530
override string toString() { result = fi.getField().toString() + "." + next.toString() }
507531

508-
override StoreChainConsCons getParent() { result.getChild() = this }
509-
510532
override StoreChain getChild() { result = next }
511533

512534
override FieldAddressInstruction getFieldInstruction() { result = fi }
@@ -563,18 +585,34 @@ private class LoadChainEndInstructionLoad extends LoadChainEndInstruction, LoadI
563585
override Instruction getReadValue() { result = getSourceValueOperand().getAnyDef() }
564586
}
565587

588+
/**
589+
* A `LoadChain` represents a series of field lookups that compute the source address of a load.
590+
* For example, given the field lookup in `f(a.b.c)`, there are two `LoadChains`s:
591+
* One corresponding to the field `b`, and one corresponding to the field `c`. Here, `b` is the parent
592+
* `LoadChain` of `c`.
593+
*/
566594
private class LoadChain extends TLoadChain {
567595
string toString() { none() }
568596

597+
/**
598+
* Gets the instruction that receives flow from the innermost `LoadChain` of this chain (i.e.,
599+
* the `LoadChain` with no child).
600+
*/
569601
LoadChainEndInstruction getEndInstruction() { none() }
570602

603+
/**
604+
* Gets the parent of this `LoadChain`, if any. For example in `f(a.b.c)` the parent of `c` is `b`,
605+
* and `b` has no parent.
606+
*/
571607
final LoadChainConsCons getParent() { result.getChild() = this }
572608

609+
/** Gets the child of this `LoadChain`, if any. */
573610
LoadChain getChild() { none() }
574611

612+
/** Gets the `FieldAddressInstruction` of this `LoadChain` */
575613
FieldAddressInstruction getFieldInstruction() { none() }
576614

577-
Location getLocation() { none() }
615+
final Location getLocation() { result = getFieldInstruction().getLocation() }
578616
}
579617

580618
private class LoadChainConsNil extends LoadChain, TLoadChainConsNil {
@@ -588,8 +626,6 @@ private class LoadChainConsNil extends LoadChain, TLoadChainConsNil {
588626
override LoadChainEndInstruction getEndInstruction() { result = end }
589627

590628
override FieldAddressInstruction getFieldInstruction() { result = fi }
591-
592-
override Location getLocation() { result = fi.getLocation() }
593629
}
594630

595631
private class LoadChainConsCons extends LoadChain, TLoadChainConsCons {
@@ -605,11 +641,21 @@ private class LoadChainConsCons extends LoadChain, TLoadChainConsCons {
605641
override LoadChain getChild() { result = next }
606642

607643
override FieldAddressInstruction getFieldInstruction() { result = fi }
608-
609-
override Location getLocation() { result = fi.getLocation() }
610644
}
611645

612-
/** `StoreNode` also extends `ReadStepNode` to participate in reverse read steps. */
646+
/**
647+
* A dataflow node generated by a partial definition.
648+
* The `StoreNode` class extends `ReadStepNode` to participate in reverse read steps.
649+
* A reverse read is a store step that is "inferred" by the DataFlow library. For example in the
650+
* assignment:
651+
* ```
652+
* a.b.c = x;
653+
* ```
654+
* Here, the access path after the store must reflect that a value has been stored into the field `c` of
655+
* the object at field `b`. The field `c` is added to the access path through a `storeStep`, and the
656+
* field `b` is inferred by the DataFlow library because there's a read step (reading the field `b`) from
657+
* the pre update node for `b.c` to the pre update node for `c`.
658+
*/
613659
private class StoreNode extends TStoreNode, StoreStepNode, ReadStepNode, PartialDefinitionNode {
614660
StoreChain storeChain;
615661

@@ -649,6 +695,7 @@ private class StoreNode extends TStoreNode, StoreStepNode, ReadStepNode, Partial
649695
}
650696
}
651697

698+
/** A dataflow node generated by loading from an address computed by a sequence of fields lookups. */
652699
private class LoadNode extends TLoadNode, ReadStepNode {
653700
LoadChain loadChain;
654701

0 commit comments

Comments
 (0)