Skip to content

Commit 5aeaab7

Browse files
committed
C++: As response to the review comments this commit adds a reference-to-pointer state to AddressFlow. A call to an unwrapper function now adds a pointer -> reference-to-pointer transition, and a ReferenceDereference adds a reference-to-pointer -> pointer transition.
1 parent 1510fe3 commit 5aeaab7

File tree

2 files changed

+116
-38
lines changed

2 files changed

+116
-38
lines changed

cpp/ql/src/semmle/code/cpp/dataflow/internal/AddressFlow.qll

Lines changed: 87 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,6 @@ private predicate pointerToLvalueStep(Expr pointerIn, Expr lvalueOut) {
5959
pointerIn = lvalueOut.(ArrayExpr).getArrayBase().getFullyConverted()
6060
or
6161
pointerIn = lvalueOut.(PointerDereferenceExpr).getOperand().getFullyConverted()
62-
or
63-
pointerIn = lvalueOut.(OverloadedPointerDereferenceExpr).getQualifier().getFullyConverted()
6462
}
6563

6664
private predicate lvalueToPointerStep(Expr lvalueIn, Expr pointerOut) {
@@ -69,6 +67,19 @@ private predicate lvalueToPointerStep(Expr lvalueIn, Expr pointerOut) {
6967
lvalueIn = pointerOut.(AddressOfExpr).getOperand().getFullyConverted()
7068
}
7169

70+
/**
71+
* Since pointer wrappers behave as raw pointers, we treat the conversions from `lvalueToLvalueStepPure`
72+
* as pointer-to-pointer steps when they involve pointer wrappers.
73+
*/
74+
private predicate pointerWrapperToPointerWrapperStep(Expr pointerIn, Expr pointerOut) {
75+
pointerIn.getUnspecifiedType() instanceof PointerWrapper and
76+
pointerIn.getConversion() = pointerOut and
77+
pointerOut.(CStyleCast).isImplicit()
78+
or
79+
pointerOut.getUnspecifiedType() instanceof PointerWrapper and
80+
pointerIn.getConversion() = pointerOut.(ReferenceDereferenceExpr)
81+
}
82+
7283
private predicate pointerToPointerStep(Expr pointerIn, Expr pointerOut) {
7384
(
7485
pointerOut instanceof PointerAddExpr
@@ -93,35 +104,60 @@ private predicate pointerToPointerStep(Expr pointerIn, Expr pointerOut) {
93104
pointerIn = pointerOut.(CommaExpr).getRightOperand().getFullyConverted()
94105
or
95106
pointerIn = pointerOut.(StmtExpr).getResultExpr().getFullyConverted()
107+
or
108+
pointerWrapperToPointerWrapperStep(pointerIn, pointerOut)
96109
}
97110

98111
private predicate lvalueToReferenceStep(Expr lvalueIn, Expr referenceOut) {
99112
lvalueIn.getConversion() = referenceOut.(ReferenceToExpr)
100-
or
101-
exists(PointerWrapper wrapper, Call call | call = referenceOut |
102-
referenceOut.getUnspecifiedType() instanceof ReferenceType and
103-
call = wrapper.getAnUnwrapperFunction().getACallToThisFunction() and
104-
lvalueIn = call.getQualifier().getFullyConverted()
105-
)
106113
}
107114

108115
private predicate referenceToLvalueStep(Expr referenceIn, Expr lvalueOut) {
109116
referenceIn.getConversion() = lvalueOut.(ReferenceDereferenceExpr)
110117
}
111118

119+
private predicate referenceToPointerToPointerStep(Expr referenceToPointerIn, Expr pointerOut) {
120+
exists(CopyConstructor copy, Call call | call = pointerOut |
121+
copy.getDeclaringType() instanceof PointerWrapper and
122+
call.getTarget() = copy and
123+
// The 0'th argument is the value being copied.
124+
referenceToPointerIn = call.getArgument(0).getFullyConverted()
125+
)
126+
or
127+
referenceToPointerIn.getConversion() = pointerOut.(ReferenceDereferenceExpr)
128+
}
129+
130+
/**
131+
* This predicate exists only to support "fake pointer" objects like
132+
* smart pointers. We treat these as raw pointers for dataflow purposes.
133+
*/
134+
private predicate referenceToPointerToUpdate(
135+
Expr referenceToPointer, Expr outer, ControlFlowNode node
136+
) {
137+
exists(Call call |
138+
node = call and
139+
outer = call.getAnArgument().getFullyConverted() and
140+
not stdIdentityFunction(call.getTarget()) and
141+
not stdAddressOf(call.getTarget()) and
142+
exists(ReferenceType rt | rt = outer.getType().stripTopLevelSpecifiers() |
143+
rt.getBaseType().getUnspecifiedType() =
144+
any(PointerWrapper wrapper | not wrapper.pointsToConst())
145+
)
146+
) and
147+
referenceToPointer = outer
148+
or
149+
exists(Expr pointerMid |
150+
referenceToPointerToPointerStep(referenceToPointer, pointerMid) and
151+
pointerToUpdate(pointerMid, outer, node)
152+
)
153+
}
154+
112155
private predicate referenceToPointerStep(Expr referenceIn, Expr pointerOut) {
113156
pointerOut =
114157
any(FunctionCall call |
115158
stdAddressOf(call.getTarget()) and
116159
referenceIn = call.getArgument(0).getFullyConverted()
117160
)
118-
or
119-
exists(CopyConstructor copy, Call call | call = pointerOut |
120-
copy.getDeclaringType() instanceof PointerWrapper and
121-
call.getTarget() = copy and
122-
// The 0'th argument is the value being copied.
123-
referenceIn = call.getArgument(0).getFullyConverted()
124-
)
125161
}
126162

127163
private predicate referenceToReferenceStep(Expr referenceIn, Expr referenceOut) {
@@ -238,6 +274,16 @@ private predicate pointerToUpdate(Expr pointer, Expr outer, ControlFlowNode node
238274
pointerToPointerStep(pointer, pointerMid) and
239275
pointerToUpdate(pointerMid, outer, node)
240276
)
277+
or
278+
exists(Expr referenceMid |
279+
pointerToReferenceStep(pointer, referenceMid) and
280+
referenceToUpdate(referenceMid, outer, node)
281+
)
282+
or
283+
exists(Expr referenceToPointerMid |
284+
pointerToReferenceToPointerStep(pointer, referenceToPointerMid) and
285+
referenceToPointerToUpdate(referenceToPointerMid, outer, node)
286+
)
241287
}
242288

243289
private predicate referenceToUpdate(Expr reference, Expr outer, ControlFlowNode node) {
@@ -247,9 +293,7 @@ private predicate referenceToUpdate(Expr reference, Expr outer, ControlFlowNode
247293
not stdIdentityFunction(call.getTarget()) and
248294
not stdAddressOf(call.getTarget()) and
249295
exists(ReferenceType rt | rt = outer.getType().stripTopLevelSpecifiers() |
250-
not rt.getBaseType().isConst() or
251-
rt.getBaseType().getUnspecifiedType() =
252-
any(PointerWrapper wrapper | not wrapper.pointsToConst())
296+
not rt.getBaseType().isConst()
253297
)
254298
) and
255299
reference = outer
@@ -270,6 +314,14 @@ private predicate referenceToUpdate(Expr reference, Expr outer, ControlFlowNode
270314
)
271315
}
272316

317+
private predicate pointerToReferenceStep(Expr pointerIn, Expr referenceOut) {
318+
exists(PointerWrapper wrapper, Call call | call = referenceOut |
319+
referenceOut.getUnspecifiedType() instanceof ReferenceType and
320+
call = wrapper.getAnUnwrapperFunction().getACallToThisFunction() and
321+
pointerIn = call.getQualifier().getFullyConverted()
322+
)
323+
}
324+
273325
private predicate lvalueFromVariableAccess(VariableAccess va, Expr lvalue) {
274326
// Base case for non-reference types.
275327
lvalue = va and
@@ -331,6 +383,21 @@ private predicate referenceFromVariableAccess(VariableAccess va, Expr reference)
331383
lvalueFromVariableAccess(va, prev) and
332384
lvalueToReferenceStep(prev, reference)
333385
)
386+
or
387+
exists(Expr prev |
388+
pointerFromVariableAccess(va, prev) and
389+
pointerToReferenceStep(prev, reference)
390+
)
391+
}
392+
393+
private predicate pointerToReferenceToPointerStep(Expr pointerIn, Expr referenceToPointerOut) {
394+
pointerIn.getConversion() = referenceToPointerOut.(ReferenceToExpr)
395+
or
396+
exists(PointerWrapper wrapper, Call call | call = referenceToPointerOut |
397+
referenceToPointerOut.getUnspecifiedType() instanceof ReferenceType and
398+
call = wrapper.getAnUnwrapperFunction().getACallToThisFunction() and
399+
pointerIn = call.getQualifier().getFullyConverted()
400+
)
334401
}
335402

336403
/**
@@ -351,6 +418,8 @@ predicate valueToUpdate(Expr inner, Expr outer, ControlFlowNode node) {
351418
pointerToUpdate(inner, outer, node)
352419
or
353420
referenceToUpdate(inner, outer, node)
421+
or
422+
referenceToPointerToUpdate(inner, outer, node)
354423
) and
355424
(
356425
inner instanceof VariableAccess and

0 commit comments

Comments
 (0)