Skip to content

Commit 75b7d4c

Browse files
committed
Data flow: Track access path singleton info
1 parent c1b19fb commit 75b7d4c

2 files changed

Lines changed: 45 additions & 30 deletions

File tree

shared/dataflow/codeql/dataflow/internal/DataFlowImpl.qll

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2859,12 +2859,16 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
28592859
Typ getTyp(Type t) { any() }
28602860

28612861
bindingset[c, tail]
2862-
Ap apCons(Content c, Ap tail) { result.getAHead() = c and exists(tail) }
2862+
Ap apCons(Content c, Ap tail) {
2863+
exists(boolean isSingleton | result.getAHead(isSingleton) = c |
2864+
if tail instanceof ApNil then isSingleton = true else isSingleton = false
2865+
)
2866+
}
28632867

28642868
class ApHeadContent = ContentApprox;
28652869

28662870
pragma[noinline]
2867-
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() }
2871+
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead(_) }
28682872

28692873
predicate projectToHeadContent = getContentApproxCached/1;
28702874

@@ -2910,7 +2914,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
29102914
PrevStage::revFlow(node) and
29112915
PrevStage::readStepCand(_, c, _) and
29122916
Stage1::expectsContentEx(node, c) and
2913-
c = ap.getAHead()
2917+
c = ap.getAHead(_)
29142918
)
29152919
}
29162920

@@ -2961,12 +2965,17 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
29612965
Typ getTyp(Type t) { any() }
29622966

29632967
bindingset[c, tail]
2964-
Ap apCons(Content c, Ap tail) { result.getHead() = c and exists(tail) }
2968+
Ap apCons(Content c, Ap tail) {
2969+
exists(boolean isSingleton |
2970+
result.getHead(isSingleton) = c and
2971+
if tail instanceof ApNil then isSingleton = true else isSingleton = false
2972+
)
2973+
}
29652974

29662975
class ApHeadContent = Content;
29672976

29682977
pragma[noinline]
2969-
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() }
2978+
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead(_) }
29702979

29712980
ApHeadContent projectToHeadContent(Content c) { result = c }
29722981

@@ -3012,19 +3021,19 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
30123021
// When `node` is the target of a store, we interpret `clearsContent` as
30133022
// only pertaining to _earlier_ store steps. In this case, we need to postpone
30143023
// checking `clearsContent` to the step creation.
3015-
clearContent(node, ap.getHead(), false)
3024+
clearContent(node, ap.getHead(_), false)
30163025
}
30173026

30183027
pragma[nomagic]
3019-
private predicate clearExceptStore(Nd node, Ap ap) { clearContent(node, ap.getHead(), true) }
3028+
private predicate clearExceptStore(Nd node, Ap ap) { clearContent(node, ap.getHead(_), true) }
30203029

30213030
pragma[nomagic]
30223031
private predicate expectsContentCand(Nd node, Ap ap) {
30233032
exists(Content c |
30243033
PrevStage::revFlow(node) and
30253034
PrevStage::readStepCand(_, c, _) and
30263035
Stage1::expectsContentEx(node, c) and
3027-
c = ap.getHead()
3036+
c = ap.getHead(_)
30283037
)
30293038
}
30303039

@@ -3059,9 +3068,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
30593068
tails = strictcount(AccessPathFront apf | Stage4::consCand(c, apf)) and
30603069
nodes =
30613070
strictcount(Nd n |
3062-
Stage4::revFlow(n, any(AccessPathFrontHead apf | apf.getHead() = c))
3071+
Stage4::revFlow(n, any(AccessPathFrontHead apf | apf.getHead(_) = c))
30633072
or
3064-
Stage4::nodeMayUseSummary(n, any(AccessPathFrontHead apf | apf.getHead() = c))
3073+
Stage4::nodeMayUseSummary(n, any(AccessPathFrontHead apf | apf.getHead(_) = c))
30653074
) and
30663075
accessPathApproxCostLimits(apLimit, tupleLimit) and
30673076
apLimit < tails and
@@ -3077,7 +3086,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
30773086
not expensiveLen2unfolding(c)
30783087
} or
30793088
TConsCons(Content c1, Content c2, int len) {
3080-
Stage4::consCand(c1, TFrontHead(c2)) and
3089+
Stage4::consCand(c1, TFrontHead(c2, _)) and
30813090
len in [2 .. Config::accessPathLimit()] and
30823091
not expensiveLen2unfolding(c1)
30833092
} or
@@ -3131,7 +3140,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
31313140

31323141
override int len() { result = 1 }
31333142

3134-
override AccessPathFront getFront() { result = TFrontHead(c) }
3143+
override AccessPathFront getFront() { result = TFrontHead(c, true) }
31353144

31363145
override predicate isCons(Content head, AccessPathApprox tail) { head = c and tail = TNil() }
31373146
}
@@ -3153,7 +3162,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
31533162

31543163
override int len() { result = len }
31553164

3156-
override AccessPathFront getFront() { result = TFrontHead(c1) }
3165+
override AccessPathFront getFront() { result = TFrontHead(c1, false) }
31573166

31583167
override predicate isCons(Content head, AccessPathApprox tail) {
31593168
head = c1 and
@@ -3184,12 +3193,14 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
31843193

31853194
override int len() { result = len }
31863195

3187-
override AccessPathFront getFront() { result = TFrontHead(c) }
3196+
override AccessPathFront getFront() {
3197+
if len = 1 then result = TFrontHead(c, true) else result = TFrontHead(c, false)
3198+
}
31883199

31893200
override predicate isCons(Content head, AccessPathApprox tail) {
31903201
head = c and
31913202
(
3192-
exists(Content c2 | Stage4::consCand(c, TFrontHead(c2)) |
3203+
exists(Content c2 | Stage4::consCand(c, TFrontHead(c2, _)) |
31933204
tail = TConsCons(c2, _, len - 1)
31943205
or
31953206
len = 2 and
@@ -3531,7 +3542,11 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
35313542

35323543
override predicate isCons(Content head, AccessPath tail) { head = head_ and tail = tail_ }
35333544

3534-
override AccessPathFrontHead getFront() { result = TFrontHead(head_) }
3545+
override AccessPathFrontHead getFront() {
3546+
if tail_.length() = 0
3547+
then result = TFrontHead(head_, true)
3548+
else result = TFrontHead(head_, false)
3549+
}
35353550

35363551
override AccessPathApproxCons getApprox() {
35373552
result = TConsNil(head_) and tail_ = TAccessPathNil()
@@ -3586,7 +3601,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
35863601
tail.length() = len - 1
35873602
}
35883603

3589-
override AccessPathFrontHead getFront() { result = TFrontHead(head1) }
3604+
override AccessPathFrontHead getFront() { result = TFrontHead(head1, false) }
35903605

35913606
override AccessPathApproxCons getApprox() {
35923607
result = TConsCons(head1, head2, len) or
@@ -3618,7 +3633,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
36183633
tail.length() = len - 1
36193634
}
36203635

3621-
override AccessPathFrontHead getFront() { result = TFrontHead(head_) }
3636+
override AccessPathFrontHead getFront() {
3637+
if len = 1 then result = TFrontHead(head_, true) else result = TFrontHead(head_, false)
3638+
}
36223639

36233640
override AccessPathApproxCons getApprox() { result = TCons1(head_, len) }
36243641

shared/dataflow/codeql/dataflow/internal/DataFlowImplCommon.qll

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1797,12 +1797,12 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
17971797
cached
17981798
newtype TAccessPathFront =
17991799
TFrontNil() or
1800-
TFrontHead(Content c)
1800+
TFrontHead(Content c, Boolean isSingleton)
18011801

18021802
cached
18031803
newtype TApproxAccessPathFront =
18041804
TApproxFrontNil() or
1805-
TApproxFrontHead(ContentApprox c)
1805+
TApproxFrontHead(ContentApprox c, Boolean isSingleton)
18061806

18071807
cached
18081808
newtype TAccessPathFrontOption =
@@ -2505,14 +2505,11 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
25052505

25062506
abstract boolean toBoolNonEmpty();
25072507

2508-
ContentApprox getHead() { this = TApproxFrontHead(result) }
2508+
ContentApprox getHead(boolean isSingleton) { this = TApproxFrontHead(result, isSingleton) }
25092509

25102510
pragma[nomagic]
2511-
Content getAHead() {
2512-
exists(ContentApprox cont |
2513-
this = TApproxFrontHead(cont) and
2514-
cont = getContentApproxCached(result)
2515-
)
2511+
Content getAHead(boolean isSingleton) {
2512+
this.getHead(isSingleton) = getContentApproxCached(result)
25162513
}
25172514
}
25182515

@@ -2525,7 +2522,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
25252522
class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead {
25262523
private ContentApprox c;
25272524

2528-
ApproxAccessPathFrontHead() { this = TApproxFrontHead(c) }
2525+
ApproxAccessPathFrontHead() { this = TApproxFrontHead(c, _) }
25292526

25302527
override string toString() { result = c.toString() }
25312528

@@ -2549,7 +2546,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
25492546

25502547
abstract ApproxAccessPathFront toApprox();
25512548

2552-
Content getHead() { this = TFrontHead(result) }
2549+
Content getHead(boolean isSingleton) { this = TFrontHead(result, isSingleton) }
25532550
}
25542551

25552552
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
@@ -2560,12 +2557,13 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
25602557

25612558
class AccessPathFrontHead extends AccessPathFront, TFrontHead {
25622559
private Content c;
2560+
private boolean isSingleton;
25632561

2564-
AccessPathFrontHead() { this = TFrontHead(c) }
2562+
AccessPathFrontHead() { this = TFrontHead(c, isSingleton) }
25652563

25662564
override string toString() { result = c.toString() }
25672565

2568-
override ApproxAccessPathFront toApprox() { result.getAHead() = c }
2566+
override ApproxAccessPathFront toApprox() { result.getAHead(isSingleton) = c }
25692567
}
25702568

25712569
/** An optional access path front. */

0 commit comments

Comments
 (0)