Skip to content

Commit 2329b31

Browse files
committed
C++: Replace the new SmartPointerPartialDefinition with additional steps in AddressFlow.qll
1 parent a460e3a commit 2329b31

File tree

7 files changed

+169
-89
lines changed

7 files changed

+169
-89
lines changed

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
*/
1616

1717
private import cpp
18+
private import semmle.code.cpp.models.interfaces.PointerWrapper
1819

1920
/**
2021
* Holds if `f` is an instantiation of the `std::move` or `std::forward`
@@ -58,6 +59,8 @@ private predicate pointerToLvalueStep(Expr pointerIn, Expr lvalueOut) {
5859
pointerIn = lvalueOut.(ArrayExpr).getArrayBase().getFullyConverted()
5960
or
6061
pointerIn = lvalueOut.(PointerDereferenceExpr).getOperand().getFullyConverted()
62+
or
63+
pointerIn = lvalueOut.(OverloadedPointerDereferenceExpr).getQualifier().getFullyConverted()
6164
}
6265

6366
private predicate lvalueToPointerStep(Expr lvalueIn, Expr pointerOut) {
@@ -94,6 +97,12 @@ private predicate pointerToPointerStep(Expr pointerIn, Expr pointerOut) {
9497

9598
private predicate lvalueToReferenceStep(Expr lvalueIn, Expr referenceOut) {
9699
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+
)
97106
}
98107

99108
private predicate referenceToLvalueStep(Expr referenceIn, Expr lvalueOut) {
@@ -106,6 +115,13 @@ private predicate referenceToPointerStep(Expr referenceIn, Expr pointerOut) {
106115
stdAddressOf(call.getTarget()) and
107116
referenceIn = call.getArgument(0).getFullyConverted()
108117
)
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+
)
109125
}
110126

111127
private predicate referenceToReferenceStep(Expr referenceIn, Expr referenceOut) {
@@ -190,6 +206,19 @@ private predicate pointerToUpdate(Expr pointer, Expr outer, ControlFlowNode node
190206
// See the `lvalueToUpdate` case for an explanation of this conjunct.
191207
call.getType().isDeeplyConstBelow()
192208
)
209+
or
210+
// Pointer wrappers behave as raw pointers for dataflow purposes.
211+
outer = call.getAnArgument().getFullyConverted() and
212+
exists(PointerWrapper wrapper | wrapper = outer.getType().stripTopLevelSpecifiers() |
213+
not wrapper.pointsToConst()
214+
)
215+
or
216+
outer = call.getQualifier().getFullyConverted() and
217+
outer.getUnspecifiedType() instanceof PointerWrapper and
218+
not (
219+
call.getTarget().hasSpecifier("const") and
220+
call.getType().isDeeplyConstBelow()
221+
)
193222
)
194223
or
195224
exists(PointerFieldAccess fa |

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

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,6 @@ class DefinitionByReferenceOrIteratorNode extends PartialDefinitionNode {
199199
this.getPartialDefinition() instanceof DefinitionByReference
200200
or
201201
this.getPartialDefinition() instanceof DefinitionByIterator
202-
or
203-
this.getPartialDefinition() instanceof DefinitionBySmartPointer
204202
)
205203
}
206204

@@ -332,18 +330,6 @@ private class IteratorPartialDefinitionNode extends PartialDefinitionNode {
332330
override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) }
333331
}
334332

335-
/**
336-
* INTERNAL: do not use.
337-
*
338-
* A synthetic data flow node used for flow into a collection when a smart pointer
339-
* write occurs in a callee.
340-
*/
341-
private class SmartPointerPartialDefinitionNode extends PartialDefinitionNode {
342-
override SmartPointerPartialDefinition pd;
343-
344-
override Node getPreUpdateNode() { pd.definesExpressions(_, result.asExpr()) }
345-
}
346-
347333
/**
348334
* A post-update node on the `e->f` in `f(&e->f)` (and other forms).
349335
*/

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

Lines changed: 0 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -242,39 +242,6 @@ private module PartialDefinitions {
242242
}
243243
}
244244

245-
class SmartPointerPartialDefinition extends PartialDefinition {
246-
Variable pointer;
247-
Expr innerDefinedExpr;
248-
249-
SmartPointerPartialDefinition() {
250-
innerDefinedExpr = pragma[only_bind_out](getInnerDefinedExpr(this, node)) and
251-
innerDefinedExpr = getAPointerWrapperAccess(pointer, -1)
252-
or
253-
// Pointer wrappers passed to a function by value.
254-
exists(Call call |
255-
call = node and
256-
call.getAnArgument() = innerDefinedExpr and
257-
innerDefinedExpr = this and
258-
this = getAPointerWrapperAccess(pointer, 0) and
259-
not call instanceof OverloadedPointerDereferenceExpr
260-
)
261-
}
262-
263-
deprecated override predicate partiallyDefines(Variable v) { v = pointer }
264-
265-
deprecated override predicate partiallyDefinesThis(ThisExpr e) { none() }
266-
267-
override predicate definesExpressions(Expr inner, Expr outer) {
268-
inner = innerDefinedExpr and
269-
outer = this
270-
}
271-
272-
override predicate partiallyDefinesVariableAt(Variable v, ControlFlowNode cfn) {
273-
v = pointer and
274-
cfn = node
275-
}
276-
}
277-
278245
/**
279246
* A partial definition that's a definition via an output iterator.
280247
*/
@@ -288,15 +255,6 @@ private module PartialDefinitions {
288255
class DefinitionByReference extends VariablePartialDefinition {
289256
DefinitionByReference() { exists(Call c | this = c.getAnArgument() or this = c.getQualifier()) }
290257
}
291-
292-
/**
293-
* A partial definition that's a definition via a smart pointer being passed into a function.
294-
*/
295-
class DefinitionBySmartPointer extends SmartPointerPartialDefinition {
296-
DefinitionBySmartPointer() {
297-
exists(Call c | this = c.getAnArgument() or this = c.getQualifier())
298-
}
299-
}
300258
}
301259

302260
import PartialDefinitions
@@ -876,22 +834,6 @@ module FlowVar_internal {
876834
)
877835
}
878836

879-
/**
880-
* Gets either:
881-
* - A call to an unwrapper function, where an access to `pointer` is the qualifier, or
882-
* - A call to the `CopyConstructor` that copies the value of an access to `pointer`.
883-
*/
884-
Call getAPointerWrapperAccess(Variable pointer, int n) {
885-
exists(PointerWrapper wrapper | wrapper = pointer.getUnspecifiedType().stripType() |
886-
n = -1 and
887-
result.getQualifier() = pointer.getAnAccess() and
888-
result.getTarget() = wrapper.getAnUnwrapperFunction()
889-
or
890-
result.getArgument(n) = pointer.getAnAccess() and
891-
result.getTarget() instanceof CopyConstructor
892-
)
893-
}
894-
895837
class IteratorParameter extends Parameter {
896838
IteratorParameter() { this.getUnspecifiedType() instanceof Iterator }
897839
}

cpp/ql/src/semmle/code/cpp/models/implementations/SmartPointer.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ private class UniqueOrSharedPtr extends Class, PointerWrapper {
1313
or
1414
result.getClassAndName(["operator->", "get"]) = this
1515
}
16+
17+
override predicate pointsToConst() { this.getTemplateArgument(0).(Type).isConst() }
1618
}
1719

1820
/** Any function that unwraps a pointer wrapper class to reveal the underlying pointer. */

cpp/ql/src/semmle/code/cpp/models/interfaces/PointerWrapper.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@ abstract class PointerWrapper extends Class {
1111
* that return a reference to the pointed-to object.
1212
*/
1313
abstract MemberFunction getAnUnwrapperFunction();
14+
15+
/** Holds if the type of the data that is pointed to by this pointer wrapper is `const`. */
16+
abstract predicate pointsToConst();
1417
}

0 commit comments

Comments
 (0)