Skip to content

Commit b0e255e

Browse files
committed
C++: Encapsulate skipSkippableInstructions in a module.
1 parent f12ebe8 commit b0e255e

File tree

2 files changed

+61
-67
lines changed

2 files changed

+61
-67
lines changed

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

Lines changed: 6 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ private predicate instrToFieldNodeStoreStepNoChi(
240240
exists(StoreInstruction store, PartialFieldDefinition pd |
241241
pd = node2.getPartialDefinition() and
242242
not exists(ChiInstruction chi | chi.getPartial() = store) and
243-
pd.getPreUpdateNode() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and
243+
pd.getPreUpdateNode() = GetFieldNode::fromInstruction(store.getDestinationAddress()) and
244244
store.getSourceValueOperand() = node1.asOperand() and
245245
f.getADirectField() = pd.getPreUpdateNode().getField()
246246
)
@@ -262,7 +262,7 @@ private predicate instrToFieldNodeStoreStepChi(
262262
node1.asOperand() = operand and
263263
chi.getPartialOperand() = operand and
264264
store = operand.getDef() and
265-
pd.getPreUpdateNode() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and
265+
pd.getPreUpdateNode() = GetFieldNode::fromInstruction(store.getDestinationAddress()) and
266266
f.getADirectField() = pd.getPreUpdateNode().getField()
267267
)
268268
}
@@ -277,7 +277,7 @@ private predicate callableWithoutDefinitionStoreStep(
277277
chi.getPartial() = write and
278278
not chi.isResultConflated() and
279279
pd = node2.getPartialDefinition() and
280-
pd.getPreUpdateNode() = getFieldNodeForFieldInstruction(write.getDestinationAddress()) and
280+
pd.getPreUpdateNode() = GetFieldNode::fromInstruction(write.getDestinationAddress()) and
281281
f.getADirectField() = pd.getPreUpdateNode().getField() and
282282
call = write.getPrimaryInstruction() and
283283
callable = call.getStaticCallTarget() and
@@ -346,24 +346,6 @@ private class ArrayToPointerConvertInstruction extends ConvertInstruction {
346346
}
347347
}
348348

349-
/**
350-
* These two predicates look like copy-paste from the two predicates with the same name in DataFlowUtil,
351-
* but crucially they only skip past `CopyValueInstruction`s. This is because we use a special case of
352-
* a `ConvertInstruction` to detect some read steps from arrays that undergoes array-to-pointer
353-
* conversion.
354-
*/
355-
private Instruction skipOneCopyValueInstructionRec(CopyValueInstruction copy) {
356-
copy.getUnary() = result and not result instanceof CopyValueInstruction
357-
or
358-
result = skipOneCopyValueInstructionRec(copy.getUnary())
359-
}
360-
361-
private Instruction skipCopyValueInstructions(Operand op) {
362-
not result instanceof CopyValueInstruction and result = op.getDef()
363-
or
364-
result = skipOneCopyValueInstructionRec(op.getDef())
365-
}
366-
367349
private class InexactLoadOperand extends LoadOperand {
368350
InexactLoadOperand() { this.isDefinitionInexact() }
369351
}
@@ -407,12 +389,12 @@ private predicate instrToFieldNodeReadStep(FieldNode node1, FieldContent f, Node
407389
(
408390
exists(LoadInstruction load |
409391
node2.asInstruction() = load and
410-
node1 = getFieldNodeForFieldInstruction(load.getSourceAddress())
392+
node1 = GetFieldNode::fromInstruction(load.getSourceAddress())
411393
)
412394
or
413395
exists(ReadSideEffectInstruction read |
414396
node2.asOperand() = read.getSideEffectOperand() and
415-
node1 = getFieldNodeForFieldInstruction(read.getArgumentDef())
397+
node1 = GetFieldNode::fromInstruction(read.getArgumentDef())
416398
)
417399
)
418400
) and
@@ -424,7 +406,7 @@ private int unbindInt(int i) { i <= result and i >= result }
424406

425407
pragma[noinline]
426408
private FieldNode getFieldNodeFromLoadOperand(LoadOperand loadOperand) {
427-
result = getFieldNodeForFieldInstruction(loadOperand.getAddressOperand().getDef())
409+
result = GetFieldNode::fromOperand(loadOperand.getAddressOperand())
428410
}
429411

430412
/**

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

Lines changed: 55 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -185,54 +185,66 @@ class OperandNode extends Node, TOperandNode {
185185
override string toString() { result = this.getOperand().toString() }
186186
}
187187

188-
/** An abstract class that defines conversion-like instructions. */
189-
abstract private class SkippableInstruction extends Instruction {
190-
abstract Instruction getSourceInstruction();
191-
}
192-
193188
/**
194-
* Gets the instruction that is propaged through a non-empty sequence of conversion-like instructions.
189+
* INTERNAL: do not use. Encapsulates the details of getting a `FieldNode` from
190+
* an `Instruction` or an `Operand`.
195191
*/
196-
private Instruction skipSkippableInstructionsRec(SkippableInstruction skip) {
197-
result = skip.getSourceInstruction() and not result instanceof SkippableInstruction
198-
or
199-
result = skipSkippableInstructionsRec(skip.getSourceInstruction())
200-
}
192+
module GetFieldNode {
193+
/** An abstract class that defines conversion-like instructions. */
194+
abstract private class SkippableInstruction extends Instruction {
195+
abstract Instruction getSourceInstruction();
196+
}
201197

202-
/**
203-
* Gets the instruction that is propagated through a (possibly empty) sequence of conversion-like
204-
* instructions.
205-
*/
206-
private Instruction skipSkippableInstructions(Instruction instr) {
207-
result = instr and not result instanceof SkippableInstruction
208-
or
209-
result = skipSkippableInstructionsRec(instr)
210-
}
198+
/**
199+
* Gets the instruction that is propaged through a non-empty sequence of conversion-like instructions.
200+
*/
201+
private Instruction skipSkippableInstructionsRec(SkippableInstruction skip) {
202+
result = skip.getSourceInstruction() and not result instanceof SkippableInstruction
203+
or
204+
result = skipSkippableInstructionsRec(skip.getSourceInstruction())
205+
}
211206

212-
private class SkippableCopyValueInstruction extends SkippableInstruction, CopyValueInstruction {
213-
override Instruction getSourceInstruction() { result = this.getSourceValue() }
214-
}
207+
/**
208+
* Gets the instruction that is propagated through a (possibly empty) sequence of conversion-like
209+
* instructions.
210+
*/
211+
private Instruction skipSkippableInstructions(Instruction instr) {
212+
result = instr and not result instanceof SkippableInstruction
213+
or
214+
result = skipSkippableInstructionsRec(instr)
215+
}
215216

216-
private class SkippableConvertInstruction extends SkippableInstruction, ConvertInstruction {
217-
override Instruction getSourceInstruction() { result = this.getUnary() }
218-
}
217+
private class SkippableCopyValueInstruction extends SkippableInstruction, CopyValueInstruction {
218+
override Instruction getSourceInstruction() { result = this.getSourceValue() }
219+
}
219220

220-
private class SkippableCheckedConvertInstruction extends SkippableInstruction,
221-
CheckedConvertOrNullInstruction {
222-
override Instruction getSourceInstruction() { result = this.getUnary() }
223-
}
221+
private class SkippableConvertInstruction extends SkippableInstruction, ConvertInstruction {
222+
override Instruction getSourceInstruction() { result = this.getUnary() }
223+
}
224224

225-
private class SkippableInheritanceConversionInstruction extends SkippableInstruction,
226-
InheritanceConversionInstruction {
227-
override Instruction getSourceInstruction() { result = this.getUnary() }
228-
}
225+
private class SkippableCheckedConvertInstruction extends SkippableInstruction,
226+
CheckedConvertOrNullInstruction {
227+
override Instruction getSourceInstruction() { result = this.getUnary() }
228+
}
229229

230-
/**
231-
* INTERNAL: do not use. Gets the `FieldNode` corresponding to `instr`, if
232-
* `instr` is an instruction that propagates an address of a `FieldAddressInstruction`.
233-
*/
234-
FieldNode getFieldNodeForFieldInstruction(Instruction instr) {
235-
result.getFieldInstruction() = skipSkippableInstructions(instr)
230+
private class SkippableInheritanceConversionInstruction extends SkippableInstruction,
231+
InheritanceConversionInstruction {
232+
override Instruction getSourceInstruction() { result = this.getUnary() }
233+
}
234+
235+
/**
236+
* INTERNAL: do not use. Gets the `FieldNode` corresponding to `instr`, if
237+
* `instr` is an instruction that propagates an address of a `FieldAddressInstruction`.
238+
*/
239+
FieldNode fromInstruction(Instruction instr) {
240+
result.getFieldInstruction() = skipSkippableInstructions(instr)
241+
}
242+
243+
/**
244+
* INTERNAL: do not use. Gets the `FieldNode` corresponding to `op`, if the definition
245+
* of `op` is an instruction that propagates an address of a `FieldAddressInstruction`.
246+
*/
247+
FieldNode fromOperand(Operand op) { result = fromInstruction(op.getDef()) }
236248
}
237249

238250
/**
@@ -265,7 +277,7 @@ class FieldNode extends Node, TFieldNode {
265277
* gives the `FieldNode` of `b`, and `f.getObjectNode().getObjectNode()` has no result as `a` is
266278
* not a field.
267279
*/
268-
FieldNode getObjectNode() { result = getFieldNodeForFieldInstruction(field.getObjectAddress()) }
280+
FieldNode getObjectNode() { result = GetFieldNode::fromInstruction(field.getObjectAddress()) }
269281

270282
/**
271283
* Gets the `FieldNode` that has this `FieldNode` as parent, if any.
@@ -683,7 +695,7 @@ private predicate flowOutOfPostUpdate(PartialDefinitionNode nodeFrom, Node nodeT
683695
exists(AddressOperand addressOperand, PartialFieldDefinition pd |
684696
pd = nodeFrom.getPartialDefinition() and
685697
not exists(pd.getPreUpdateNode().getObjectNode()) and
686-
pd.getPreUpdateNode().getNextNode*() = getFieldNodeForFieldInstruction(addressOperand.getDef()) and
698+
pd.getPreUpdateNode().getNextNode*() = GetFieldNode::fromOperand(addressOperand) and
687699
(
688700
exists(ChiInstruction chi |
689701
nodeTo.asInstruction() = chi and
@@ -711,7 +723,7 @@ private predicate flowOutOfPostUpdate(PartialDefinitionNode nodeFrom, Node nodeT
711723
*/
712724
private FieldNode getOutermostFieldNode(Instruction address) {
713725
not exists(result.getObjectNode()) and
714-
result.getNextNode*() = getFieldNodeForFieldInstruction(address)
726+
result.getNextNode*() = GetFieldNode::fromInstruction(address)
715727
}
716728

717729
private predicate flowIntoReadNode(Node nodeFrom, FieldNode nodeTo) {

0 commit comments

Comments
 (0)