Skip to content

Commit 86f7ccf

Browse files
committed
Merge branch 'main' into cpp-access-paths-for-sources-and-sinks-3
2 parents 6d91ebe + f2ce282 commit 86f7ccf

8 files changed

Lines changed: 141 additions & 56 deletions

File tree

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Initializers of compiler-generated variables are now recognized as compiler-generated. A new predicate `isCompilerGenerated` on `Initializer` has been added to reflect this.

cpp/ql/lib/semmle/code/cpp/Initializer.qll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,15 @@ class Initializer extends ControlFlowNode, @initialiser {
5454

5555
/** Holds if the initializer used the C++ braced initializer notation. */
5656
predicate isBraced() { braced_initialisers(underlyingElement(this)) }
57+
58+
/** Holds if this initializer is generated by the compiler. */
59+
predicate isCompilerGenerated() {
60+
exists(Variable v |
61+
v = this.getDeclaration() and
62+
// We require the variable to be an orphan to not mark the initializer
63+
// from a desugared ranged for loop as compiler generated.
64+
orphaned_variables(unresolveElement(v), _) and
65+
v.isCompilerGenerated()
66+
)
67+
}
5768
}

cpp/ql/lib/semmle/code/cpp/exprs/Expr.qll

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,8 @@ class Expr extends StmtParent, @expr {
108108
/** Holds if this is an auxiliary expression generated by the compiler. */
109109
predicate isCompilerGenerated() {
110110
compgenerated(underlyingElement(this)) or
111-
this.getParent().(ConstructorFieldInit).isCompilerGenerated()
111+
this.getParent().(ConstructorFieldInit).isCompilerGenerated() or
112+
this.getParent().(Initializer).isCompilerGenerated()
112113
}
113114

114115
/**

cpp/ql/test/library-tests/compiler_generated/compilerGenerated.expected

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,31 @@
1616
| cpp.cpp:15:5:15:12 | call to ~MyClass | Expr |
1717
| cpp.cpp:15:12:15:12 | reuse of m | Expr |
1818
| cpp.cpp:16:1:16:1 | return ... | Stmt |
19+
| cpp.cpp:19:26:19:44 | __PRETTY_FUNCTION__ | Variable |
20+
| cpp.cpp:19:26:19:44 | array to pointer conversion | Expr |
21+
| cpp.cpp:19:26:19:44 | initializer for __PRETTY_FUNCTION__ | Initializer |
22+
| cpp.cpp:19:26:19:44 | void uses_pretty_function() | Expr |
23+
| cpp.cpp:20:1:20:1 | return ... | Stmt |
24+
| cpp.cpp:23:29:23:32 | args | Variable |
25+
| cpp.cpp:23:37:23:37 | return ... | Stmt |
26+
| cpp.cpp:23:37:23:37 | return ... | Stmt |
27+
| cpp.cpp:27:1:27:1 | return ... | Stmt |
28+
| cpp.cpp:31:5:31:5 | (__begin) | Variable |
29+
| cpp.cpp:31:5:31:5 | (__end) | Variable |
30+
| cpp.cpp:31:5:31:5 | (__range) | Variable |
31+
| cpp.cpp:31:5:33:5 | declaration | Stmt |
32+
| cpp.cpp:31:5:33:5 | declaration | Stmt |
33+
| cpp.cpp:31:5:33:5 | declaration | Stmt |
34+
| cpp.cpp:31:17:31:18 | (reference to) | Expr |
35+
| cpp.cpp:34:1:34:1 | return ... | Stmt |
36+
| file://:0:0:0:0 | (__begin) | Expr |
37+
| file://:0:0:0:0 | (__begin) | Expr |
38+
| file://:0:0:0:0 | (__begin) | Expr |
39+
| file://:0:0:0:0 | (__end) | Expr |
40+
| file://:0:0:0:0 | (reference dereference) | Expr |
41+
| file://:0:0:0:0 | (reference dereference) | Expr |
42+
| file://:0:0:0:0 | * ... | Expr |
43+
| file://:0:0:0:0 | array to pointer conversion | Expr |
44+
| file://:0:0:0:0 | array to pointer conversion | Expr |
1945
| file://:0:0:0:0 | operator delete | Function |
2046
| file://:0:0:0:0 | operator new | Function |

cpp/ql/test/library-tests/compiler_generated/compilerGenerated.ql

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,6 @@ where
99
e.(Variable).isCompilerGenerated() and type = "Variable"
1010
or
1111
e.(Stmt).isCompilerGenerated() and type = "Stmt"
12+
or
13+
e.(Initializer).isCompilerGenerated() and type = "Initializer"
1214
select e, type

cpp/ql/test/library-tests/compiler_generated/cpp.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,20 @@ void g1(void) {
1515
delete m;
1616
}
1717

18+
void uses_pretty_function() {
19+
const char* pretty = __PRETTY_FUNCTION__;
20+
}
21+
22+
template <typename... Args>
23+
void parameter_pack(Args... args) { }
24+
25+
void test_parameter_pack() {
26+
parameter_pack();
27+
}
28+
29+
void ranged_for() {
30+
int vs[] = {1, 2, 3};
31+
for(int i : vs) {
32+
33+
}
34+
}

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

Lines changed: 55 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
370370
}
371371

372372
class Ap {
373+
/** Gets the tracked length of this access path, if any. */
374+
int length();
375+
373376
string toString();
374377
}
375378

@@ -563,10 +566,10 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
563566

564567
pragma[nomagic]
565568
private int getAnApLengthLowerBound(Ap ap) {
566-
accessPathLimit() > 1 and // `accessPathLimit() <= 1` is already checked in stages 1 and 2
567-
ap instanceof ApNil and
568-
result = 0
569+
accessPathLimit() != 0 and // `accessPathLimit() = 0` is already checked in `useFieldFlow`
570+
result = ap.length()
569571
or
572+
not exists(ap.length()) and
570573
exists(Ap tail |
571574
fwdFlowConsCand(_, ap, _, _, tail) and
572575
ap != tail and // no need to report a longer length
@@ -609,9 +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
613-
then getAnApLengthLowerBound(ap0) < accessPathLimit()
614-
else any()
615+
getAnApLengthLowerBound(ap0) < accessPathLimit()
615616
)
616617
or
617618
// read
@@ -1339,10 +1340,10 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
13391340

13401341
pragma[nomagic]
13411342
private int getAnApLengthLowerBoundRev(Ap ap) {
1342-
accessPathLimit() > 1 and // `accessPathLimit() <= 1` is already checked in stages 1 and 2
1343-
ap instanceof ApNil and
1344-
result = 0
1343+
accessPathLimit() != 0 and // `accessPathLimit() = 0` is already checked in `useFieldFlow`
1344+
result = ap.length()
13451345
or
1346+
not exists(ap.length()) and
13461347
exists(Ap tail |
13471348
revFlowConsCand(ap, _, tail) and
13481349
ap != tail and // no need to report a longer length
@@ -1388,9 +1389,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
13881389
exists(Nd mid, Ap ap0 |
13891390
revFlow(mid, returnCtx, returnAp, ap0) and
13901391
readStepFwd(node, ap, _, mid, ap0) and
1391-
if accessPathLimit() > 1
1392-
then getAnApLengthLowerBoundRev(ap0) < accessPathLimit()
1393-
else any()
1392+
getAnApLengthLowerBoundRev(ap0) < accessPathLimit()
13941393
)
13951394
or
13961395
// flow into a callable
@@ -2770,7 +2769,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
27702769

27712770
class Typ = Unit;
27722771

2773-
class Ap = Boolean;
2772+
class Ap extends Boolean {
2773+
int length() { this = false and result = 0 }
2774+
}
27742775

27752776
class ApNil extends Ap {
27762777
ApNil() { this = false }
@@ -2859,12 +2860,19 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
28592860
Typ getTyp(Type t) { any() }
28602861

28612862
bindingset[c, tail]
2862-
Ap apCons(Content c, Ap tail) { result.getAHead() = c and exists(tail) }
2863+
Ap apCons(Content c, Ap tail) {
2864+
exists(int length | result.getAHead(length) = c |
2865+
length = 1 and
2866+
tail instanceof ApNil
2867+
or
2868+
tail = TApproxFrontHead(_, length - 1)
2869+
)
2870+
}
28632871

28642872
class ApHeadContent = ContentApprox;
28652873

28662874
pragma[noinline]
2867-
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() }
2875+
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead(_) }
28682876

28692877
predicate projectToHeadContent = getContentApproxCached/1;
28702878

@@ -2910,7 +2918,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
29102918
PrevStage::revFlow(node) and
29112919
PrevStage::readStepCand(_, c, _) and
29122920
Stage1::expectsContentEx(node, c) and
2913-
c = ap.getAHead()
2921+
c = ap.getAHead(_)
29142922
)
29152923
}
29162924

@@ -2961,12 +2969,19 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
29612969
Typ getTyp(Type t) { any() }
29622970

29632971
bindingset[c, tail]
2964-
Ap apCons(Content c, Ap tail) { result.getHead() = c and exists(tail) }
2972+
Ap apCons(Content c, Ap tail) {
2973+
exists(int length | result.getHead(length) = c |
2974+
length = 1 and
2975+
tail instanceof ApNil
2976+
or
2977+
tail = TFrontHead(_, length - 1)
2978+
)
2979+
}
29652980

29662981
class ApHeadContent = Content;
29672982

29682983
pragma[noinline]
2969-
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead() }
2984+
ApHeadContent getHeadContent(Ap ap) { result = ap.getHead(_) }
29702985

29712986
ApHeadContent projectToHeadContent(Content c) { result = c }
29722987

@@ -3012,19 +3027,19 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
30123027
// When `node` is the target of a store, we interpret `clearsContent` as
30133028
// only pertaining to _earlier_ store steps. In this case, we need to postpone
30143029
// checking `clearsContent` to the step creation.
3015-
clearContent(node, ap.getHead(), false)
3030+
clearContent(node, ap.getHead(_), false)
30163031
}
30173032

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

30213036
pragma[nomagic]
30223037
private predicate expectsContentCand(Nd node, Ap ap) {
30233038
exists(Content c |
30243039
PrevStage::revFlow(node) and
30253040
PrevStage::readStepCand(_, c, _) and
30263041
Stage1::expectsContentEx(node, c) and
3027-
c = ap.getHead()
3042+
c = ap.getHead(_)
30283043
)
30293044
}
30303045

@@ -3059,9 +3074,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
30593074
tails = strictcount(AccessPathFront apf | Stage4::consCand(c, apf)) and
30603075
nodes =
30613076
strictcount(Nd n |
3062-
Stage4::revFlow(n, any(AccessPathFrontHead apf | apf.getHead() = c))
3077+
Stage4::revFlow(n, any(AccessPathFrontHead apf | apf.getHead(_) = c))
30633078
or
3064-
Stage4::nodeMayUseSummary(n, any(AccessPathFrontHead apf | apf.getHead() = c))
3079+
Stage4::nodeMayUseSummary(n, any(AccessPathFrontHead apf | apf.getHead(_) = c))
30653080
) and
30663081
accessPathApproxCostLimits(apLimit, tupleLimit) and
30673082
apLimit < tails and
@@ -3077,7 +3092,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
30773092
not expensiveLen2unfolding(c)
30783093
} or
30793094
TConsCons(Content c1, Content c2, int len) {
3080-
Stage4::consCand(c1, TFrontHead(c2)) and
3095+
Stage4::consCand(c1, TFrontHead(c2, len - 1)) and
30813096
len in [2 .. Config::accessPathLimit()] and
30823097
not expensiveLen2unfolding(c1)
30833098
} or
@@ -3098,7 +3113,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
30983113

30993114
abstract Content getHead();
31003115

3101-
abstract int len();
3116+
abstract int length();
31023117

31033118
abstract AccessPathFront getFront();
31043119

@@ -3111,7 +3126,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
31113126

31123127
override Content getHead() { none() }
31133128

3114-
override int len() { result = 0 }
3129+
override int length() { result = 0 }
31153130

31163131
override AccessPathFront getFront() { result = TFrontNil() }
31173132

@@ -3129,9 +3144,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
31293144

31303145
override Content getHead() { result = c }
31313146

3132-
override int len() { result = 1 }
3147+
override int length() { result = 1 }
31333148

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

31363151
override predicate isCons(Content head, AccessPathApprox tail) { head = c and tail = TNil() }
31373152
}
@@ -3151,9 +3166,9 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
31513166

31523167
override Content getHead() { result = c1 }
31533168

3154-
override int len() { result = len }
3169+
override int length() { result = len }
31553170

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

31583173
override predicate isCons(Content head, AccessPathApprox tail) {
31593174
head = c1 and
@@ -3182,14 +3197,14 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
31823197

31833198
override Content getHead() { result = c }
31843199

3185-
override int len() { result = len }
3200+
override int length() { result = len }
31863201

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

31893204
override predicate isCons(Content head, AccessPathApprox tail) {
31903205
head = c and
31913206
(
3192-
exists(Content c2 | Stage4::consCand(c, TFrontHead(c2)) |
3207+
exists(Content c2 | Stage4::consCand(c, TFrontHead(c2, len - 1)) |
31933208
tail = TConsCons(c2, _, len - 1)
31943209
or
31953210
len = 2 and
@@ -3288,7 +3303,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
32883303

32893304
pragma[nomagic]
32903305
private predicate stage5ConsCand(Content c, AccessPathFront apf, int len) {
3291-
Stage5::consCand(c, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1))
3306+
Stage5::consCand(c, any(AccessPathApprox ap | ap.getFront() = apf and ap.length() = len - 1))
32923307
}
32933308

32943309
/**
@@ -3297,7 +3312,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
32973312
private int count1to2unfold(AccessPathApproxCons1 apa) {
32983313
exists(Content c, int len |
32993314
c = apa.getHead() and
3300-
len = apa.len() and
3315+
len = apa.length() and
33013316
result = strictcount(AccessPathFront apf | stage5ConsCand(c, apf, len))
33023317
)
33033318
}
@@ -3392,7 +3407,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
33923407
exists(AccessPathApproxCons apa, AccessPathApprox tail |
33933408
evalUnfold(apa, false) and
33943409
not expensiveLen1to2unfolding(apa) and
3395-
apa.len() = len and
3410+
apa.length() = len and
33963411
hasTail(apa, tail) and
33973412
head1 = apa.getHead() and
33983413
head2 = tail.getHead()
@@ -3402,7 +3417,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
34023417
exists(AccessPathApproxCons apa |
34033418
evalUnfold(apa, false) and
34043419
expensiveLen1to2unfolding(apa) and
3405-
apa.len() = len and
3420+
apa.length() = len and
34063421
head = apa.getHead()
34073422
)
34083423
}
@@ -3531,7 +3546,7 @@ module MakeImpl<LocationSig Location, InputSig<Location> Lang> {
35313546

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

3534-
override AccessPathFrontHead getFront() { result = TFrontHead(head_) }
3549+
override AccessPathFrontHead getFront() { result = TFrontHead(head_, this.length()) }
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, len) }
35903605

35913606
override AccessPathApproxCons getApprox() {
35923607
result = TConsCons(head1, head2, len) or
@@ -3618,7 +3633,7 @@ 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() { result = TFrontHead(head_, len) }
36223637

36233638
override AccessPathApproxCons getApprox() { result = TCons1(head_, len) }
36243639

0 commit comments

Comments
 (0)