Skip to content

Commit 41fd0d6

Browse files
committed
Data flow: Track access path lengths in stages 3 and 4
1 parent c1b19fb commit 41fd0d6

2 files changed

Lines changed: 60 additions & 35 deletions

File tree

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

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
375375

376376
class ApNil extends Ap;
377377

378+
predicate apTracksLength();
379+
378380
bindingset[result, ap]
379381
ApApprox getApprox(Ap ap);
380382

@@ -563,6 +565,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
563565

564566
pragma[nomagic]
565567
private int getAnApLengthLowerBound(Ap ap) {
568+
not apTracksLength() and // no need if we are tracking precise length information
566569
accessPathLimit() > 1 and // `accessPathLimit() <= 1` is already checked in stages 1 and 2
567570
ap instanceof ApNil and
568571
result = 0
@@ -609,7 +612,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
609612
fwdFlowStore(_, _, ap0, _, c, t, stored, node, cc, summaryCtx) and
610613
ap = apCons(c, ap0) and
611614
apa = getApprox(ap) and
612-
if accessPathLimit() > 1
615+
if accessPathLimit() > 1 and not apTracksLength()
613616
then getAnApLengthLowerBound(ap0) < accessPathLimit()
614617
else any()
615618
)
@@ -1339,6 +1342,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
13391342

13401343
pragma[nomagic]
13411344
private int getAnApLengthLowerBoundRev(Ap ap) {
1345+
not apTracksLength() and // no need if we are tracking precise length information
13421346
accessPathLimit() > 1 and // `accessPathLimit() <= 1` is already checked in stages 1 and 2
13431347
ap instanceof ApNil and
13441348
result = 0
@@ -1388,7 +1392,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
13881392
exists(Nd mid, Ap ap0 |
13891393
revFlow(mid, returnCtx, returnAp, ap0) and
13901394
readStepFwd(node, ap, _, mid, ap0) and
1391-
if accessPathLimit() > 1
1395+
if accessPathLimit() > 1 and not apTracksLength()
13921396
then getAnApLengthLowerBoundRev(ap0) < accessPathLimit()
13931397
else any()
13941398
)
@@ -2776,6 +2780,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
27762780
ApNil() { this = false }
27772781
}
27782782

2783+
predicate apTracksLength() { none() }
2784+
27792785
bindingset[result, ap]
27802786
PrevStage::Ap getApprox(Ap ap) { any() }
27812787

@@ -2854,17 +2860,26 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
28542860

28552861
class ApNil = ApproxAccessPathFrontNil;
28562862

2863+
predicate apTracksLength() { any() }
2864+
28572865
PrevStage::Ap getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
28582866

28592867
Typ getTyp(Type t) { any() }
28602868

28612869
bindingset[c, tail]
2862-
Ap apCons(Content c, Ap tail) { result.getAHead() = c and exists(tail) }
2870+
Ap apCons(Content c, Ap tail) {
2871+
exists(int length | result.getAHead(length) = c |
2872+
length = 1 and
2873+
tail instanceof ApNil
2874+
or
2875+
tail = TApproxFrontHead(_, length - 1)
2876+
)
2877+
}
28632878

28642879
class ApHeadContent = ContentApprox;
28652880

28662881
pragma[noinline]
2867-
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() }
2882+
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead(_) }
28682883

28692884
predicate projectToHeadContent = getContentApproxCached/1;
28702885

@@ -2910,7 +2925,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
29102925
PrevStage::revFlow(node) and
29112926
PrevStage::readStepCand(_, c, _) and
29122927
Stage1::expectsContentEx(node, c) and
2913-
c = ap.getAHead()
2928+
c = ap.getAHead(_)
29142929
)
29152930
}
29162931

@@ -2956,17 +2971,26 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
29562971

29572972
class ApNil = AccessPathFrontNil;
29582973

2974+
predicate apTracksLength() { any() }
2975+
29592976
PrevStage::Ap getApprox(Ap ap) { result = ap.toApprox() }
29602977

29612978
Typ getTyp(Type t) { any() }
29622979

29632980
bindingset[c, tail]
2964-
Ap apCons(Content c, Ap tail) { result.getHead() = c and exists(tail) }
2981+
Ap apCons(Content c, Ap tail) {
2982+
exists(int length | result.getHead(length) = c |
2983+
length = 1 and
2984+
tail instanceof ApNil
2985+
or
2986+
tail = TFrontHead(_, length - 1)
2987+
)
2988+
}
29652989

29662990
class ApHeadContent = Content;
29672991

29682992
pragma[noinline]
2969-
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() }
2993+
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead(_) }
29702994

29712995
ApHeadContent projectToHeadContent(Content c) { result = c }
29722996

@@ -3012,19 +3036,19 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
30123036
// When `node` is the target of a store, we interpret `clearsContent` as
30133037
// only pertaining to _earlier_ store steps. In this case, we need to postpone
30143038
// checking `clearsContent` to the step creation.
3015-
clearContent(node, ap.getHead(), false)
3039+
clearContent(node, ap.getHead(_), false)
30163040
}
30173041

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

30213045
pragma[nomagic]
30223046
private predicate expectsContentCand(Nd node, Ap ap) {
30233047
exists(Content c |
30243048
PrevStage::revFlow(node) and
30253049
PrevStage::readStepCand(_, c, _) and
30263050
Stage1::expectsContentEx(node, c) and
3027-
c = ap.getHead()
3051+
c = ap.getHead(_)
30283052
)
30293053
}
30303054

@@ -3059,9 +3083,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
30593083
tails = strictcount(AccessPathFront apf | Stage4::consCand(c, apf)) and
30603084
nodes =
30613085
strictcount(Nd n |
3062-
Stage4::revFlow(n, any(AccessPathFrontHead apf | apf.getHead() = c))
3086+
Stage4::revFlow(n, any(AccessPathFrontHead apf | apf.getHead(_) = c))
30633087
or
3064-
Stage4::nodeMayUseSummary(n, any(AccessPathFrontHead apf | apf.getHead() = c))
3088+
Stage4::nodeMayUseSummary(n, any(AccessPathFrontHead apf | apf.getHead(_) = c))
30653089
) and
30663090
accessPathApproxCostLimits(apLimit, tupleLimit) and
30673091
apLimit < tails and
@@ -3077,7 +3101,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
30773101
not expensiveLen2unfolding(c)
30783102
} or
30793103
TConsCons(Content c1, Content c2, int len) {
3080-
Stage4::consCand(c1, TFrontHead(c2)) and
3104+
Stage4::consCand(c1, TFrontHead(c2, _)) and
30813105
len in [2 .. Config::accessPathLimit()] and
30823106
not expensiveLen2unfolding(c1)
30833107
} or
@@ -3131,7 +3155,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
31313155

31323156
override int len() { result = 1 }
31333157

3134-
override AccessPathFront getFront() { result = TFrontHead(c) }
3158+
override AccessPathFront getFront() { result = TFrontHead(c, 1) }
31353159

31363160
override predicate isCons(Content head, AccessPathApprox tail) { head = c and tail = TNil() }
31373161
}
@@ -3153,7 +3177,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
31533177

31543178
override int len() { result = len }
31553179

3156-
override AccessPathFront getFront() { result = TFrontHead(c1) }
3180+
override AccessPathFront getFront() { result = TFrontHead(c1, len) }
31573181

31583182
override predicate isCons(Content head, AccessPathApprox tail) {
31593183
head = c1 and
@@ -3184,12 +3208,12 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
31843208

31853209
override int len() { result = len }
31863210

3187-
override AccessPathFront getFront() { result = TFrontHead(c) }
3211+
override AccessPathFront getFront() { result = TFrontHead(c, len) }
31883212

31893213
override predicate isCons(Content head, AccessPathApprox tail) {
31903214
head = c and
31913215
(
3192-
exists(Content c2 | Stage4::consCand(c, TFrontHead(c2)) |
3216+
exists(Content c2 | Stage4::consCand(c, TFrontHead(c2, len - 1)) |
31933217
tail = TConsCons(c2, _, len - 1)
31943218
or
31953219
len = 2 and
@@ -3226,6 +3250,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
32263250

32273251
class ApNil = AccessPathApproxNil;
32283252

3253+
predicate apTracksLength() { any() }
3254+
32293255
pragma[nomagic]
32303256
PrevStage::Ap getApprox(Ap ap) { result = ap.getFront() }
32313257

@@ -3416,6 +3442,8 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
34163442

34173443
class ApNil = AccessPathNil;
34183444

3445+
predicate apTracksLength() { any() }
3446+
34193447
pragma[nomagic]
34203448
PrevStage::Ap getApprox(Ap ap) { result = ap.getApprox() }
34213449

@@ -3531,7 +3559,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
35313559

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

3534-
override AccessPathFrontHead getFront() { result = TFrontHead(head_) }
3562+
override AccessPathFrontHead getFront() { result = TFrontHead(head_, this.length()) }
35353563

35363564
override AccessPathApproxCons getApprox() {
35373565
result = TConsNil(head_) and tail_ = TAccessPathNil()
@@ -3586,7 +3614,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
35863614
tail.length() = len - 1
35873615
}
35883616

3589-
override AccessPathFrontHead getFront() { result = TFrontHead(head1) }
3617+
override AccessPathFrontHead getFront() { result = TFrontHead(head1, len) }
35903618

35913619
override AccessPathApproxCons getApprox() {
35923620
result = TConsCons(head1, head2, len) or
@@ -3618,7 +3646,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
36183646
tail.length() = len - 1
36193647
}
36203648

3621-
override AccessPathFrontHead getFront() { result = TFrontHead(head_) }
3649+
override AccessPathFrontHead getFront() { result = TFrontHead(head_, len) }
36223650

36233651
override AccessPathApproxCons getApprox() { result = TCons1(head_, len) }
36243652

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

Lines changed: 12 additions & 15 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, int length) { length in [1 .. accessPathLimit()] }
18011801

18021802
cached
18031803
newtype TApproxAccessPathFront =
18041804
TApproxFrontNil() or
1805-
TApproxFrontHead(ContentApprox c)
1805+
TApproxFrontHead(ContentApprox c, int length) { length in [1 .. accessPathLimit()] }
18061806

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

25062506
abstract boolean toBoolNonEmpty();
25072507

2508-
ContentApprox getHead() { this = TApproxFrontHead(result) }
2508+
ContentApprox getHead(int length) { this = TApproxFrontHead(result, length) }
25092509

25102510
pragma[nomagic]
2511-
Content getAHead() {
2512-
exists(ContentApprox cont |
2513-
this = TApproxFrontHead(cont) and
2514-
cont = getContentApproxCached(result)
2515-
)
2516-
}
2511+
Content getAHead(int length) { this.getHead(length) = getContentApproxCached(result) }
25172512
}
25182513

25192514
class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil {
@@ -2524,10 +2519,11 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
25242519

25252520
class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead {
25262521
private ContentApprox c;
2522+
private int length;
25272523

2528-
ApproxAccessPathFrontHead() { this = TApproxFrontHead(c) }
2524+
ApproxAccessPathFrontHead() { this = TApproxFrontHead(c, length) }
25292525

2530-
override string toString() { result = c.toString() }
2526+
override string toString() { result = c + " (length: " + length + ")" }
25312527

25322528
override boolean toBoolNonEmpty() { result = true }
25332529
}
@@ -2549,7 +2545,7 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
25492545

25502546
abstract ApproxAccessPathFront toApprox();
25512547

2552-
Content getHead() { this = TFrontHead(result) }
2548+
Content getHead(int length) { this = TFrontHead(result, length) }
25532549
}
25542550

25552551
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
@@ -2560,12 +2556,13 @@ module MakeImplCommon<LocationSig Location, InputSig<Location> Lang> {
25602556

25612557
class AccessPathFrontHead extends AccessPathFront, TFrontHead {
25622558
private Content c;
2559+
private int length;
25632560

2564-
AccessPathFrontHead() { this = TFrontHead(c) }
2561+
AccessPathFrontHead() { this = TFrontHead(c, length) }
25652562

2566-
override string toString() { result = c.toString() }
2563+
override string toString() { result = c + " (length: " + length + ")" }
25672564

2568-
override ApproxAccessPathFront toApprox() { result.getAHead() = c }
2565+
override ApproxAccessPathFront toApprox() { result.getAHead(length) = c }
25692566
}
25702567

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

0 commit comments

Comments
 (0)