Skip to content

Commit c9bcbf7

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 c9bcbf7

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-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: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,14 +146,55 @@ 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(), _, _) and
158+
fieldFlowsToStore(mid)
159+
)
160+
}
161+
162+
private predicate isGlobalUseIndirectDefCand(GlobalLikeVariable v, IRFunction f, CppType type) {
163+
exists(VariableAddressInstruction vai, Operand op |
164+
vai.getEnclosingIRFunction() = f and
165+
vai.getAstVariable() = v and
166+
numberOfLoadsFromOperand(vai.getAUse(), op, _, _) and
167+
type = getResultLanguageType(vai)
168+
|
169+
// Either this operand is used as the qualifier of a field that flows to
170+
// a `StoreInstruction`
171+
op = any(FieldAddress fa | fieldFlowsToStore(fa)).getObjectAddressOperand()
172+
or
173+
// Or the operand is potentially modified by a function call
174+
isModifiableByCall(op, _)
175+
)
176+
}
177+
149178
private predicate isGlobalUse(
150179
GlobalLikeVariable v, IRFunction f, int indirection, int indirectionIndex
151180
) {
181+
// Generate a "global use" at the end of the function body if there's a
182+
// direct definition somewhere in the body of the function
152183
exists(VariableAddressInstruction vai |
153184
vai.getEnclosingIRFunction() = f and
154185
vai.getAstVariable() = v and
155186
isDef(_, _, _, vai, indirection, indirectionIndex)
156187
)
188+
or
189+
// Generate a "global use" at the end of the function body if the
190+
// global variable is used for field-flow, or is passed as an argument
191+
// to a function that may change its value.
192+
exists(CppType type, int upper |
193+
isGlobalUseIndirectDefCand(v, f, type) and
194+
upper = countIndirectionsForCppType(type) and
195+
indirection = [1 .. upper] and
196+
indirectionIndex = indirection - 1
197+
)
157198
}
158199

159200
private predicate isGlobalDefImpl(

0 commit comments

Comments
 (0)