Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 91debe8

Browse files
committed
C++: Add ReadNodes and implement local flow steps into them.
1 parent ba4da72 commit 91debe8

1 file changed

Lines changed: 118 additions & 1 deletion

File tree

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

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ cached
1515
private newtype TIRDataFlowNode =
1616
TInstructionNode(Instruction i) or
1717
TOperandNode(Operand op) or
18-
TVariableNode(Variable var)
18+
TVariableNode(Variable var) or
19+
// `FieldNodes` are used as targets of certain `storeStep`s to implement handling of stores to
20+
// nested structs.
21+
TFieldNode(FieldAddressInstruction field)
1922

2023
/**
2124
* A node in a data flow graph.
@@ -170,6 +173,91 @@ class OperandNode extends Node, TOperandNode {
170173
override string toString() { result = this.getOperand().toString() }
171174
}
172175

176+
abstract private class SkippableInstruction extends Instruction {
177+
abstract Instruction getSourceInstruction();
178+
}
179+
180+
private Instruction skipSkippableInstructionsRec(SkippableInstruction skip) {
181+
result = skip.getSourceInstruction() and not result instanceof SkippableInstruction
182+
or
183+
result = skipSkippableInstructionsRec(skip.getSourceInstruction())
184+
}
185+
186+
private Instruction skipSkippableInstructions(Instruction instr) {
187+
result = instr and not result instanceof SkippableInstruction
188+
or
189+
result = skipSkippableInstructionsRec(instr)
190+
}
191+
192+
private class SkippableCopyValueInstruction extends SkippableInstruction, CopyValueInstruction {
193+
override Instruction getSourceInstruction() { result = this.getSourceValue() }
194+
}
195+
196+
private class SkippableConvertInstruction extends SkippableInstruction, ConvertInstruction {
197+
override Instruction getSourceInstruction() { result = this.getUnary() }
198+
}
199+
200+
private class SkippableCheckedConvertInstruction extends SkippableInstruction,
201+
CheckedConvertOrNullInstruction {
202+
override Instruction getSourceInstruction() { result = this.getUnary() }
203+
}
204+
205+
private class SkippableInheritanceConversionInstruction extends SkippableInstruction,
206+
InheritanceConversionInstruction {
207+
override Instruction getSourceInstruction() { result = this.getUnary() }
208+
}
209+
210+
/**
211+
* INTERNAL: do not use. Gets the `FieldNode` corresponding to `instr`, if
212+
* `instr` is an instruction that propagates an address of a `FieldAddressInstruction`.
213+
*/
214+
FieldNode getFieldNodeForFieldInstruction(Instruction instr) {
215+
result.getFieldInstruction() = skipSkippableInstructions(instr)
216+
}
217+
218+
/**
219+
* INTERNAL: do not use. A `FieldNode` represents the state of an object after modifying one
220+
* of its fields.
221+
*/
222+
class FieldNode extends Node, TFieldNode {
223+
FieldAddressInstruction field;
224+
225+
FieldNode() { this = TFieldNode(field) }
226+
227+
/** Gets the `Field` of this `FieldNode`. */
228+
Field getField() { result = getFieldInstruction().getField() }
229+
230+
/** Gets the `FieldAddressInstruction` of this `FieldNode`. */
231+
FieldAddressInstruction getFieldInstruction() { result = field }
232+
233+
/**
234+
* Gets the `FieldNode` corresponding to the parent field of this `FieldNode`, if any.
235+
*
236+
* For example, if `f` is the `FieldNode` for `c` in the expression `a.b.c`, then `f.getObjectNode()`
237+
* gives the `FieldNode` of `b`, and `f.getObjectNode().getObjectNode()` has no result as `a` is
238+
* not a field.
239+
*/
240+
FieldNode getObjectNode() { result = getFieldNodeForFieldInstruction(field.getObjectAddress()) }
241+
242+
/**
243+
* Gets the `FieldNode` that has this `FieldNode` as parent, if any.
244+
*
245+
* For example, if `f` is the `FieldNode` corresponding to `b` in `a.b.c`, then `f.getNextNode()`
246+
* gives the `FieldNode` corresponding to `c`, and `f.getNextNode().getNextNode()`.
247+
*/
248+
FieldNode getNextNode() { result.getObjectNode() = this }
249+
250+
/** Gets the class where the field of this node is declared. */
251+
Class getDeclaringType() { result = getField().getDeclaringType() }
252+
253+
override Function getFunction() { result = field.getEnclosingFunction() }
254+
255+
override IRType getType() { result = field.getResultIRType() }
256+
257+
override Location getLocation() { result = field.getLocation() }
258+
259+
override string toString() { result = this.getField().toString() }
260+
}
173261
/**
174262
* An expression, viewed as a node in a data flow graph.
175263
*/
@@ -585,6 +673,33 @@ Node uninitializedNode(LocalVariable v) { none() }
585673
*/
586674
predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFrom, nodeTo) }
587675

676+
private predicate flowIntoReadNode(Node nodeFrom, Node nodeTo) {
677+
// flow from the "innermost" field to the load of that field.
678+
exists(FieldNode fieldNode | nodeTo = fieldNode |
679+
not exists(fieldNode.getObjectNode()) and
680+
(
681+
exists(LoadInstruction load |
682+
fieldNode.getNextNode*() = getFieldNodeForFieldInstruction(load.getSourceAddress()) and
683+
nodeFrom.asInstruction() = load.getSourceValueOperand().getAnyDef()
684+
)
685+
or
686+
// We need this to make stores look like loads for the dataflow library. So when there's a store
687+
// of the form x->y = z we need to make the field node corresponding to y look like it's reading
688+
// from the memory of x.
689+
exists(StoreInstruction store, ChiInstruction chi |
690+
chi.getPartial() = store and
691+
fieldNode.getNextNode*() = getFieldNodeForFieldInstruction(store.getDestinationAddress()) and
692+
nodeFrom.asInstruction() = chi.getTotal()
693+
)
694+
or
695+
exists(ReadSideEffectInstruction read |
696+
fieldNode.getNextNode*() = getFieldNodeForFieldInstruction(read.getArgumentDef()) and
697+
nodeFrom.asOperand() = read.getSideEffectOperand()
698+
)
699+
)
700+
)
701+
}
702+
588703
/**
589704
* INTERNAL: do not use.
590705
*
@@ -598,6 +713,8 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
598713
or
599714
// Instruction -> Operand flow
600715
simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand())
716+
or
717+
flowIntoReadNode(nodeFrom, nodeTo)
601718
}
602719

603720
pragma[noinline]

0 commit comments

Comments
 (0)