Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 52e6e1d

Browse files
committed
C++: Fix flow through partial definitions.
1 parent 575ac46 commit 52e6e1d

1 file changed

Lines changed: 84 additions & 54 deletions

File tree

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll

Lines changed: 84 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ private newtype TDefOrUseImpl =
144144
indirectionIndex = [0 .. defIndex] + 1
145145
)
146146
} or
147-
TGlobalDef(Cpp::GlobalOrNamespaceVariable v, IRFunction f, int indirectionIndex) {
147+
TGlobalDefImpl(Cpp::GlobalOrNamespaceVariable v, IRFunction f, int indirectionIndex) {
148148
// Represents the initial "definition" of a global variable when entering
149149
// a function body.
150150
exists(VariableAddressInstruction vai |
@@ -475,12 +475,12 @@ class GlobalUse extends UseImpl, TGlobalUse {
475475
override BaseSourceVariableInstruction getBase() { none() }
476476
}
477477

478-
class GlobalDef extends TGlobalDef {
478+
class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
479479
Cpp::GlobalOrNamespaceVariable global;
480480
IRFunction f;
481481
int indirectionIndex;
482482

483-
GlobalDef() { this = TGlobalDef(global, f, indirectionIndex) }
483+
GlobalDefImpl() { this = TGlobalDefImpl(global, f, indirectionIndex) }
484484

485485
/** Gets the global variable associated with this definition. */
486486
Cpp::GlobalOrNamespaceVariable getVariable() { result = global }
@@ -489,43 +489,32 @@ class GlobalDef extends TGlobalDef {
489489
IRFunction getIRFunction() { result = f }
490490

491491
/** Gets the global variable associated with this definition. */
492-
int getIndirectionIndex() { result = indirectionIndex }
492+
override int getIndirectionIndex() { result = indirectionIndex }
493493

494494
/** Holds if this definition or use has index `index` in block `block`. */
495-
final predicate hasIndexInBlock(IRBlock block, int index) {
495+
final override predicate hasIndexInBlock(IRBlock block, int index) {
496496
exists(EnterFunctionInstruction enter |
497497
enter = f.getEnterFunctionInstruction() and
498498
block.getInstruction(index) = enter
499499
)
500500
}
501501

502502
/** Gets the global variable associated with this definition. */
503-
SourceVariable getSourceVariable() { sourceVariableIsGlobal(result, global, f, indirectionIndex) }
504-
505-
/**
506-
* Holds if this definition has index `index` in block `block`, and
507-
* is a definition of the variable `sv`
508-
*/
509-
final predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) {
510-
this.hasIndexInBlock(block, index) and
511-
sv = this.getSourceVariable()
512-
}
513-
514-
/** Gets the location of this element. */
515-
final Cpp::Location getLocation() { result = f.getLocation() }
516-
517-
/** Gets a textual representation of this element. */
518-
string toString() {
519-
if indirectionIndex = 0
520-
then result = global.toString()
521-
else result = global.toString() + " indirection"
503+
override SourceVariable getSourceVariable() {
504+
sourceVariableIsGlobal(result, global, f, indirectionIndex)
522505
}
523506

524507
/**
525508
* Gets the type of this use after specifiers have been deeply stripped
526509
* and typedefs have been resolved.
527510
*/
528511
Type getUnspecifiedType() { result = global.getUnspecifiedType() }
512+
513+
override string toString() { result = "GlobalDef" }
514+
515+
override Location getLocation() { result = f.getLocation() }
516+
517+
override BaseSourceVariableInstruction getBase() { none() }
529518
}
530519

531520
/**
@@ -641,33 +630,31 @@ private predicate indirectConversionFlowStep(Node nFrom, Node nTo) {
641630
* So this predicate recurses back along conversions and `PointerArithmeticInstruction`s to find the
642631
* first use that has provides use-use flow, and uses that target as the target of the `nodeFrom`.
643632
*/
644-
private predicate adjustForPointerArith(Node nodeFrom, UseOrPhi use, boolean uncertain) {
633+
private predicate adjustForPointerArith(
634+
DefOrUse defOrUse, Node nodeFrom, UseOrPhi use, boolean uncertain
635+
) {
645636
nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and
646-
exists(DefOrUse defOrUse, Node adjusted |
637+
exists(Node adjusted |
647638
indirectConversionFlowStep*(adjusted, nodeFrom) and
648639
nodeToDefOrUse(adjusted, defOrUse, uncertain) and
649640
adjacentDefRead(defOrUse, use)
650641
)
651642
}
652643

653-
private predicate ssaFlowImpl(Node nodeFrom, Node nodeTo, boolean uncertain) {
644+
private predicate ssaFlowImpl(SsaDefOrUse defOrUse, Node nodeFrom, Node nodeTo, boolean uncertain) {
654645
// `nodeFrom = any(PostUpdateNode pun).getPreUpdateNode()` is implied by adjustedForPointerArith.
655646
exists(UseOrPhi use |
656-
adjustForPointerArith(nodeFrom, use, uncertain) and
647+
adjustForPointerArith(defOrUse, nodeFrom, use, uncertain) and
657648
useToNode(use, nodeTo)
658-
)
659-
or
660-
not nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and
661-
exists(DefOrUse defOrUse1, UseOrPhi use |
662-
nodeToDefOrUse(nodeFrom, defOrUse1, uncertain) and
663-
adjacentDefRead(defOrUse1, use) and
649+
or
650+
not nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and
651+
nodeToDefOrUse(nodeFrom, defOrUse, uncertain) and
652+
adjacentDefRead(defOrUse, use) and
664653
useToNode(use, nodeTo)
665-
)
666-
or
667-
// Initial global variable value to a first use
668-
exists(GlobalDef globalDef, UseOrPhi use |
669-
nodeFrom.(InitialGlobalValue).getGlobalDef() = globalDef and
670-
globalDefToUse(globalDef, use) and
654+
or
655+
// Initial global variable value to a first use
656+
nodeFrom.(InitialGlobalValue).getGlobalDef() = defOrUse and
657+
globalDefToUse(defOrUse, use) and
671658
useToNode(use, nodeTo) and
672659
uncertain = false
673660
)
@@ -677,29 +664,28 @@ private predicate ssaFlowImpl(Node nodeFrom, Node nodeTo, boolean uncertain) {
677664
* Holds if `def` is the corresponding definition of
678665
* the SSA library's `definition`.
679666
*/
680-
private predicate ssaDefinition(Def def, Definition definition) {
667+
private Definition ssaDefinition(Def def) {
681668
exists(IRBlock block, int i, SourceVariable sv |
682669
def.hasIndexInBlock(block, i, sv) and
683-
definition.definesAt(sv, block, i)
670+
result.definesAt(sv, block, i)
684671
)
685672
}
686673

687674
/** Gets a node that represents the prior definition of `node`. */
688-
private Node getAPriorDefinition(Node node) {
689-
exists(Def def, Definition definition, Definition inp, Def input |
690-
defToNode(node, def, true) and
691-
ssaDefinition(def, definition) and
692-
uncertainWriteDefinitionInput(pragma[only_bind_into](definition), pragma[only_bind_into](inp)) and
693-
ssaDefinition(input, inp) and
694-
defToNode(result, input, _)
675+
private Node getAPriorDefinition(SsaDefOrUse defOrUse) {
676+
exists(IRBlock bb, int i, SourceVariable sv, Definition def, DefOrUse defOrUse0 |
677+
SsaCached::lastRefRedef(def, bb, i, ssaDefinition(defOrUse)) and
678+
def.getSourceVariable() = sv and
679+
defOrUse0.hasIndexInBlock(bb, i, sv) and
680+
nodeToDefOrUse(result, defOrUse0, _)
695681
)
696682
}
697683

698684
/** Holds if there is def-use or use-use flow from `nodeFrom` to `nodeTo`. */
699685
predicate ssaFlow(Node nodeFrom, Node nodeTo) {
700-
exists(Node nFrom, boolean uncertain |
701-
ssaFlowImpl(nFrom, nodeTo, uncertain) and
702-
if uncertain = true then nodeFrom = [nFrom, getAPriorDefinition(nFrom)] else nodeFrom = nFrom
686+
exists(Node nFrom, boolean uncertain, SsaDefOrUse defOrUse |
687+
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and
688+
if uncertain = true then nodeFrom = [nFrom, getAPriorDefinition(defOrUse)] else nodeFrom = nFrom
703689
)
704690
}
705691

@@ -774,7 +760,7 @@ private module SsaInput implements SsaImplCommon::InputSig {
774760
if def.isCertain() then certain = true else certain = false
775761
)
776762
or
777-
exists(GlobalDef global |
763+
exists(GlobalDefImpl global |
778764
global.hasIndexInBlock(bb, i, v) and
779765
certain = true
780766
)
@@ -839,15 +825,20 @@ private newtype TSsaDefOrUse =
839825
defOrUse.(DefImpl).hasIndexInBlock(bb, i, sv)
840826
)
841827
} or
842-
TPhi(PhiNode phi)
828+
TPhi(PhiNode phi) or
829+
TGlobalDef(GlobalDefImpl global)
843830

844831
abstract private class SsaDefOrUse extends TSsaDefOrUse {
832+
/** Gets a textual representation of this element. */
845833
string toString() { none() }
846834

835+
/** Gets the underlying non-phi definition or use. */
847836
DefOrUseImpl asDefOrUse() { none() }
848837

838+
/** Gets the underlying phi node. */
849839
PhiNode asPhi() { none() }
850840

841+
/** Gets the location of this element. */
851842
abstract Location getLocation();
852843
}
853844

@@ -864,11 +855,50 @@ class DefOrUse extends TDefOrUse, SsaDefOrUse {
864855

865856
override string toString() { result = defOrUse.toString() }
866857

858+
/**
859+
* Holds if this definition (or use) has index `index` in block `block`,
860+
* and is a definition (or use) of the variable `sv`.
861+
*/
867862
predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) {
868863
defOrUse.hasIndexInBlock(block, index, sv)
869864
}
870865
}
871866

867+
class GlobalDef extends TGlobalDef, SsaDefOrUse {
868+
GlobalDefImpl global;
869+
870+
GlobalDef() { this = TGlobalDef(global) }
871+
872+
/** Gets the location of this definition. */
873+
final override Location getLocation() { result = global.getLocation() }
874+
875+
/** Gets a textual representation of this definition. */
876+
override string toString() { result = "GlobalDef" }
877+
878+
/**
879+
* Holds if this definition has index `index` in block `block`, and
880+
* is a definition of the variable `sv`.
881+
*/
882+
predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) {
883+
global.hasIndexInBlock(block, index, sv)
884+
}
885+
886+
/** Gets the indirection index of this definition. */
887+
int getIndirectionIndex() { result = global.getIndirectionIndex() }
888+
889+
/**
890+
* Gets the type of this definition after specifiers have been deeply stripped
891+
* and typedefs have been resolved.
892+
*/
893+
DataFlowType getUnspecifiedType() { result = global.getUnspecifiedType() }
894+
895+
/** Gets the `IRFunction` whose body is evaluated after this definition. */
896+
IRFunction getIRFunction() { result = global.getIRFunction() }
897+
898+
/** Gets the global variable associated with this definition. */
899+
Cpp::GlobalOrNamespaceVariable getVariable() { result = global.getVariable() }
900+
}
901+
872902
class Phi extends TPhi, SsaDefOrUse {
873903
PhiNode phi;
874904

0 commit comments

Comments
 (0)