Skip to content

Commit eddc2f3

Browse files
author
Robert Marsh
authored
Merge pull request #11694 from MathiasVP/iterator-use-use-flow-using-ir-ssa
C++: Iterator flow for IR-based use-use flow (second attempt)
2 parents 31b4dda + a36afc6 commit eddc2f3

5 files changed

Lines changed: 367 additions & 56 deletions

File tree

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

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,15 @@ private Type getTypeImpl(Type t, int indirectionIndex) {
670670
result = t
671671
or
672672
indirectionIndex > 0 and
673-
result = getTypeImpl(stripPointer(t), indirectionIndex - 1)
673+
exists(Type stripped |
674+
stripped = stripPointer(t) and
675+
// We need to avoid the case where `stripPointer(t) = t` (which can happen on
676+
// iterators that specify a `value_type` that is the iterator itself). Such a type
677+
// would create an infinite loop otherwise. For these cases we simply don't produce
678+
// a result for `getType`.
679+
stripped.getUnspecifiedType() != t.getUnspecifiedType() and
680+
result = getTypeImpl(stripPointer(t), indirectionIndex - 1)
681+
)
674682
}
675683

676684
/**
@@ -1209,15 +1217,16 @@ private module Cached {
12091217
// the operand also flows to the indirction of the instruction.
12101218
exists(Operand operand, Instruction instr, int indirectionIndex |
12111219
simpleInstructionLocalFlowStep(operand, instr) and
1212-
hasOperandAndIndex(nodeFrom, operand, indirectionIndex) and
1213-
hasInstructionAndIndex(nodeTo, instr, indirectionIndex)
1220+
hasOperandAndIndex(nodeFrom, operand, pragma[only_bind_into](indirectionIndex)) and
1221+
hasInstructionAndIndex(nodeTo, instr, pragma[only_bind_into](indirectionIndex))
12141222
)
12151223
or
12161224
// If there's indirect flow to an operand, then there's also indirect
12171225
// flow to the operand after applying some pointer arithmetic.
12181226
exists(PointerArithmeticInstruction pointerArith, int indirectionIndex |
1219-
hasOperandAndIndex(nodeFrom, pointerArith.getAnOperand(), indirectionIndex) and
1220-
hasInstructionAndIndex(nodeTo, pointerArith, indirectionIndex)
1227+
hasOperandAndIndex(nodeFrom, pointerArith.getAnOperand(),
1228+
pragma[only_bind_into](indirectionIndex)) and
1229+
hasInstructionAndIndex(nodeTo, pointerArith, pragma[only_bind_into](indirectionIndex))
12211230
)
12221231
}
12231232

@@ -1229,8 +1238,8 @@ private module Cached {
12291238
exists(Operand operand, Instruction instr, int indirectionIndex |
12301239
simpleOperandLocalFlowStep(pragma[only_bind_into](instr), pragma[only_bind_into](operand))
12311240
|
1232-
hasOperandAndIndex(nodeTo, operand, indirectionIndex) and
1233-
hasInstructionAndIndex(nodeFrom, instr, indirectionIndex)
1241+
hasOperandAndIndex(nodeTo, operand, pragma[only_bind_into](indirectionIndex)) and
1242+
hasInstructionAndIndex(nodeFrom, instr, pragma[only_bind_into](indirectionIndex))
12341243
)
12351244
}
12361245

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

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,17 @@ private newtype TDefOrUseImpl =
119119
TUseImpl(Operand operand, int indirectionIndex) {
120120
isUse(_, operand, _, _, indirectionIndex) and
121121
not isDef(_, _, operand, _, _, _)
122+
} or
123+
TIteratorDef(
124+
Operand iteratorAddress, BaseSourceVariableInstruction container, int indirectionIndex
125+
) {
126+
isIteratorDef(container, iteratorAddress, _, _, indirectionIndex) and
127+
any(SsaInternals0::Def def | def.isIteratorDef()).getAddressOperand() = iteratorAddress
128+
} or
129+
TIteratorUse(
130+
Operand iteratorAddress, BaseSourceVariableInstruction container, int indirectionIndex
131+
) {
132+
isIteratorUse(container, iteratorAddress, _, indirectionIndex)
122133
}
123134

124135
abstract private class DefOrUseImpl extends TDefOrUseImpl {
@@ -192,21 +203,22 @@ private predicate sourceVariableHasBaseAndIndex(SourceVariable v, BaseSourceVari
192203
v.getIndirection() = ind
193204
}
194205

195-
class DefImpl extends DefOrUseImpl, TDefImpl {
206+
abstract class DefImpl extends DefOrUseImpl {
196207
Operand address;
197208
int ind;
198209

199-
DefImpl() { this = TDefImpl(address, ind) }
210+
bindingset[ind]
211+
DefImpl() { any() }
200212

201-
override BaseSourceVariableInstruction getBase() { isDef(_, _, address, result, _, _) }
213+
abstract int getIndirection();
202214

203-
Operand getAddressOperand() { result = address }
215+
abstract Node0Impl getValue();
204216

205-
int getIndirection() { isDef(_, _, address, _, result, ind) }
217+
abstract predicate isCertain();
206218

207-
override int getIndirectionIndex() { result = ind }
219+
Operand getAddressOperand() { result = address }
208220

209-
Node0Impl getValue() { isDef(_, result, address, _, _, _) }
221+
override int getIndirectionIndex() { result = ind }
210222

211223
override string toString() { result = "DefImpl" }
212224

@@ -217,15 +229,40 @@ class DefImpl extends DefOrUseImpl, TDefImpl {
217229
final override predicate hasIndexInBlock(IRBlock block, int index) {
218230
this.getAddressOperand().getUse() = block.getInstruction(index)
219231
}
232+
}
233+
234+
private class DirectDef extends DefImpl, TDefImpl {
235+
DirectDef() { this = TDefImpl(address, ind) }
236+
237+
override BaseSourceVariableInstruction getBase() { isDef(_, _, address, result, _, _) }
238+
239+
override int getIndirection() { isDef(_, _, address, _, result, ind) }
240+
241+
override Node0Impl getValue() { isDef(_, result, address, _, _, _) }
242+
243+
override predicate isCertain() { isDef(true, _, address, _, _, ind) }
244+
}
245+
246+
private class IteratorDef extends DefImpl, TIteratorDef {
247+
BaseSourceVariableInstruction container;
220248

221-
predicate isCertain() { isDef(true, _, address, _, _, ind) }
249+
IteratorDef() { this = TIteratorDef(address, container, ind) }
250+
251+
override BaseSourceVariableInstruction getBase() { result = container }
252+
253+
override int getIndirection() { isIteratorDef(container, address, _, result, ind) }
254+
255+
override Node0Impl getValue() { isIteratorDef(container, address, result, _, _) }
256+
257+
override predicate isCertain() { none() }
222258
}
223259

224-
class UseImpl extends DefOrUseImpl, TUseImpl {
260+
abstract class UseImpl extends DefOrUseImpl {
225261
Operand operand;
226262
int ind;
227263

228-
UseImpl() { this = TUseImpl(operand, ind) }
264+
bindingset[ind]
265+
UseImpl() { any() }
229266

230267
Operand getOperand() { result = operand }
231268

@@ -239,13 +276,33 @@ class UseImpl extends DefOrUseImpl, TUseImpl {
239276

240277
final override Cpp::Location getLocation() { result = operand.getLocation() }
241278

242-
final int getIndirection() { isUse(_, operand, _, result, ind) }
243-
244279
override int getIndirectionIndex() { result = ind }
245280

281+
abstract int getIndirection();
282+
283+
abstract predicate isCertain();
284+
}
285+
286+
private class DirectUse extends UseImpl, TUseImpl {
287+
DirectUse() { this = TUseImpl(operand, ind) }
288+
289+
override int getIndirection() { isUse(_, operand, _, result, ind) }
290+
246291
override BaseSourceVariableInstruction getBase() { isUse(_, operand, result, _, ind) }
247292

248-
predicate isCertain() { isUse(true, operand, _, _, ind) }
293+
override predicate isCertain() { isUse(true, operand, _, _, ind) }
294+
}
295+
296+
private class IteratorUse extends UseImpl, TIteratorUse {
297+
BaseSourceVariableInstruction container;
298+
299+
IteratorUse() { this = TIteratorUse(operand, container, ind) }
300+
301+
override int getIndirection() { isIteratorUse(container, operand, result, ind) }
302+
303+
override BaseSourceVariableInstruction getBase() { result = container }
304+
305+
override predicate isCertain() { none() }
249306
}
250307

251308
/**

0 commit comments

Comments
 (0)