Skip to content

Commit f665295

Browse files
committed
C++: Synthesize a final use of a global variable if a global variable is passed into a function, or if the global variable is used for field-flow.
1 parent a3d3617 commit f665295

File tree

2 files changed

+43
-3
lines changed

2 files changed

+43
-3
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -780,9 +780,7 @@ private predicate numberOfLoadsFromOperandRec(
780780
* Holds if `operandFrom` flows to `operandTo` using a sequence of conversion-like
781781
* operations and exactly `n` `LoadInstruction` operations.
782782
*/
783-
private predicate numberOfLoadsFromOperand(
784-
Operand operandFrom, Operand operandTo, int n, boolean certain
785-
) {
783+
predicate numberOfLoadsFromOperand(Operand operandFrom, Operand operandTo, int n, boolean certain) {
786784
numberOfLoadsFromOperandRec(operandFrom, operandTo, n, certain)
787785
or
788786
not Ssa::isDereference(_, operandFrom, _) and

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,56 @@ private newtype TDefOrUseImpl =
146146
)
147147
}
148148

149+
/**
150+
* Holds if `fa` flows to a the address of a `StoreInstruction`, or flows to
151+
* the qualifier of another field address that transitively flows to a `StoreInstruction`.
152+
*/
153+
private predicate fieldFlowsToStore(FieldAddress fa) {
154+
numberOfLoadsFromOperand(fa, any(StoreInstruction store).getDestinationAddressOperand(), _, _)
155+
or
156+
exists(FieldAddress mid |
157+
numberOfLoadsFromOperand(fa, mid.getObjectAddressOperand(), _, _)
158+
or
159+
fieldFlowsToStore(mid)
160+
)
161+
}
162+
163+
private predicate isGlobalUseIndirectDefCand(GlobalLikeVariable v, IRFunction f, CppType type) {
164+
exists(VariableAddressInstruction vai, Operand op |
165+
vai.getEnclosingIRFunction() = f and
166+
vai.getAstVariable() = v and
167+
numberOfLoadsFromOperand(vai.getAUse(), op, _, _) and
168+
type = getResultLanguageType(vai)
169+
|
170+
// Either this operand is used as the qualifier of a field that flows to
171+
// a `StoreInstruction`
172+
op = any(FieldAddress fa | fieldFlowsToStore(fa)).getObjectAddressOperand()
173+
or
174+
// Or the operand is potentially modified by a function call
175+
isModifiableByCall(op, _)
176+
)
177+
}
178+
149179
private predicate isGlobalUse(
150180
GlobalLikeVariable v, IRFunction f, int indirection, int indirectionIndex
151181
) {
182+
// Generate a "global use" at the end of the function body if there's a
183+
// direct definition somewhere in the body of the function
152184
exists(VariableAddressInstruction vai |
153185
vai.getEnclosingIRFunction() = f and
154186
vai.getAstVariable() = v and
155187
isDef(_, _, _, vai, indirection, indirectionIndex)
156188
)
189+
or
190+
// Generate a "global use" at the end of the function body if the
191+
// global variable is used for field-flow, or is passed as an argument
192+
// to a function that may change its value.
193+
exists(CppType type, int upper |
194+
isGlobalUseIndirectDefCand(v, f, type) and
195+
upper = countIndirectionsForCppType(type) and
196+
indirection = [1 .. upper] and
197+
indirectionIndex = indirection - 1
198+
)
157199
}
158200

159201
private predicate isGlobalDefImpl(

0 commit comments

Comments
 (0)