mirror of
https://github.com/github/codeql.git
synced 2025-12-20 10:46:30 +01:00
C++: Add field flow and accept tests
This commit is contained in:
@@ -131,7 +131,14 @@ private class ArrayContent extends Content, TArrayContent {
|
||||
* value of `node1`.
|
||||
*/
|
||||
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
|
||||
none() // stub implementation
|
||||
exists(FieldAddressInstruction fa |
|
||||
exists(StoreInstruction store |
|
||||
node1.asInstruction() = store and
|
||||
store.getDestinationAddress() = fa
|
||||
) and
|
||||
node2.getPreUpdateNode().asInstruction() = fa.getObjectAddress() and
|
||||
f.(FieldContent).getField() = fa.getField()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,7 +147,12 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
|
||||
* `node2`.
|
||||
*/
|
||||
predicate readStep(Node node1, Content f, Node node2) {
|
||||
none() // stub implementation
|
||||
exists(FieldAddressInstruction fa, LoadInstruction load |
|
||||
load.getSourceAddress() = fa and
|
||||
node1.asInstruction() = fa.getObjectAddress() and
|
||||
fa.getField() = f.(FieldContent).getField() and
|
||||
load = node2.asInstruction()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -63,6 +63,9 @@ class Node extends TIRDataFlowNode {
|
||||
*/
|
||||
Variable asVariable() { result = this.(VariableNode).getVariable() }
|
||||
|
||||
Expr asPartialDefinition() {
|
||||
result = this.(PartialDefinitionNode).getInstruction().getUnconvertedResultExpression()
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: See UninitializedNode.
|
||||
@@ -213,6 +216,19 @@ abstract class PostUpdateNode extends InstructionNode {
|
||||
* Gets the node before the state update.
|
||||
*/
|
||||
abstract Node getPreUpdateNode();
|
||||
|
||||
override string toString() { result = getPreUpdateNode().toString() + " [post update]" }
|
||||
}
|
||||
|
||||
abstract class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { }
|
||||
|
||||
class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
|
||||
override StoreInstruction instr;
|
||||
FieldAddressInstruction field;
|
||||
|
||||
ExplicitFieldStoreQualifierNode() { field = instr.getDestinationAddress() }
|
||||
|
||||
override Node getPreUpdateNode() { result.asInstruction() = field.getObjectAddress() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -225,24 +241,24 @@ abstract class PostUpdateNode extends InstructionNode {
|
||||
* returned. This node will have its `getArgument()` equal to `&x` and its
|
||||
* `getVariableAccess()` equal to `x`.
|
||||
*/
|
||||
class DefinitionByReferenceNode extends InstructionNode {
|
||||
class DefinitionByReferenceNode extends PartialDefinitionNode {
|
||||
override WriteSideEffectInstruction instr;
|
||||
CallInstruction call;
|
||||
|
||||
DefinitionByReferenceNode() { call = instr.getPrimaryInstruction() }
|
||||
|
||||
override Node getPreUpdateNode() {
|
||||
result.asInstruction() = call.getPositionalArgument(instr.getIndex())
|
||||
or
|
||||
result.asInstruction() = call.getThisArgument() and
|
||||
instr.getIndex() = -1
|
||||
}
|
||||
|
||||
/** Gets the argument corresponding to this node. */
|
||||
Expr getArgument() {
|
||||
result =
|
||||
instr
|
||||
.getPrimaryInstruction()
|
||||
.(CallInstruction)
|
||||
.getPositionalArgument(instr.getIndex())
|
||||
.getUnconvertedResultExpression()
|
||||
result = call.getPositionalArgument(instr.getIndex()).getUnconvertedResultExpression()
|
||||
or
|
||||
result =
|
||||
instr
|
||||
.getPrimaryInstruction()
|
||||
.(CallInstruction)
|
||||
.getThisArgument()
|
||||
.getUnconvertedResultExpression() and
|
||||
result = call.getThisArgument().getUnconvertedResultExpression() and
|
||||
instr.getIndex() = -1
|
||||
}
|
||||
|
||||
@@ -250,6 +266,24 @@ class DefinitionByReferenceNode extends InstructionNode {
|
||||
Parameter getParameter() {
|
||||
exists(CallInstruction ci | result = ci.getStaticCallTarget().getParameter(instr.getIndex()))
|
||||
}
|
||||
|
||||
override string toString() { result = "ref arg " + getPreUpdateNode().toString() }
|
||||
}
|
||||
|
||||
class PositionalArgumentWithoutWriteSideEffectNode extends PartialDefinitionNode {
|
||||
override CallInstruction instr;
|
||||
PositionalArgumentOperand op;
|
||||
|
||||
PositionalArgumentWithoutWriteSideEffectNode() {
|
||||
instr.getAnOperand() = op and
|
||||
not exists(WriteSideEffectInstruction write |
|
||||
write.getIndex() = op.getIndex() and write.getPrimaryInstruction() = instr
|
||||
)
|
||||
}
|
||||
|
||||
override Node getPreUpdateNode() { result.asInstruction() = op.getDef() }
|
||||
|
||||
override string toString() { result = "no change to " + op.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -332,6 +366,13 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr
|
||||
*/
|
||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
simpleInstructionLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asInstruction())
|
||||
or
|
||||
exists(ChiInstruction chi, LoadInstruction load |
|
||||
chi.getPartial() = nodeFrom.(PartialDefinitionNode).getInstruction() and
|
||||
// TODO: This can probably be getSourceValue() after #3112 is merged
|
||||
load.getSourceValueOperand().getAnyDef() = chi and
|
||||
nodeTo.asInstruction() = load.getSourceAddress().(FieldAddressInstruction).getObjectAddress()
|
||||
)
|
||||
}
|
||||
|
||||
private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo) {
|
||||
|
||||
@@ -1,27 +1,87 @@
|
||||
edges
|
||||
| A.cpp:126:5:126:5 | ref arg b [c] : void | A.cpp:131:8:131:8 | ref arg b [c] : void |
|
||||
| A.cpp:126:12:126:18 | new : void | A.cpp:126:5:126:5 | ref arg b [c] : void |
|
||||
| A.cpp:131:8:131:8 | ref arg b [c] : void | A.cpp:132:10:132:10 | b [c] : void |
|
||||
| A.cpp:132:10:132:10 | b [c] : void | A.cpp:132:13:132:13 | c |
|
||||
| A.cpp:132:10:132:10 | b [c] : void | A.cpp:132:13:132:13 | c : void |
|
||||
| A.cpp:132:13:132:13 | c : void | A.cpp:132:10:132:13 | (void *)... |
|
||||
| aliasing.cpp:9:3:9:22 | s [post update] : void | aliasing.cpp:9:3:9:22 | s [post update] [m1] : void |
|
||||
| aliasing.cpp:9:3:9:22 | s [post update] [m1] : void | aliasing.cpp:25:17:25:19 | ref arg & ... [m1] : void |
|
||||
| aliasing.cpp:9:11:9:20 | call to user_input : void | aliasing.cpp:9:3:9:22 | s [post update] : void |
|
||||
| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] : void | aliasing.cpp:13:3:13:21 | (reference dereference) [post update] [m1] : void |
|
||||
| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] [m1] : void | aliasing.cpp:26:19:26:20 | ref arg (reference to) [m1] : void |
|
||||
| aliasing.cpp:13:10:13:19 | call to user_input : void | aliasing.cpp:13:3:13:21 | (reference dereference) [post update] : void |
|
||||
| aliasing.cpp:25:17:25:19 | ref arg & ... [m1] : void | aliasing.cpp:29:8:29:9 | s1 [m1] : void |
|
||||
| aliasing.cpp:26:19:26:20 | ref arg (reference to) [m1] : void | aliasing.cpp:30:8:30:9 | s2 [m1] : void |
|
||||
| aliasing.cpp:29:8:29:9 | s1 [m1] : void | aliasing.cpp:29:11:29:12 | m1 |
|
||||
| aliasing.cpp:30:8:30:9 | s2 [m1] : void | aliasing.cpp:30:11:30:12 | m1 |
|
||||
| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | aliasing.cpp:38:11:38:12 | m1 |
|
||||
| aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void |
|
||||
| aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 |
|
||||
| aliasing.cpp:42:3:42:22 | s2 [post update] : void | aliasing.cpp:43:13:43:14 | m1 |
|
||||
| aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:42:3:42:22 | s2 [post update] : void |
|
||||
| aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 |
|
||||
| aliasing.cpp:79:3:79:22 | s [post update] : void | aliasing.cpp:80:12:80:13 | m1 |
|
||||
| aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:79:3:79:22 | s [post update] : void |
|
||||
| aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 |
|
||||
| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | aliasing.cpp:87:12:87:13 | m1 |
|
||||
| aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void |
|
||||
| aliasing.cpp:86:10:86:19 | call to user_input : void | aliasing.cpp:87:12:87:13 | m1 |
|
||||
| aliasing.cpp:92:3:92:23 | s [post update] : void | aliasing.cpp:93:12:93:13 | m1 |
|
||||
| aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:92:3:92:23 | s [post update] : void |
|
||||
| aliasing.cpp:92:12:92:21 | call to user_input : void | aliasing.cpp:93:12:93:13 | m1 |
|
||||
| struct_init.c:20:20:20:29 | VariableAddress [post update] : void | struct_init.c:22:11:22:11 | a |
|
||||
| struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:20:20:20:29 | VariableAddress [post update] : void |
|
||||
| struct_init.c:20:20:20:29 | call to user_input : void | struct_init.c:22:11:22:11 | a |
|
||||
| struct_init.c:27:7:27:16 | FieldAddress [post update] : void | struct_init.c:31:23:31:23 | a |
|
||||
| struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:27:7:27:16 | FieldAddress [post update] : void |
|
||||
| struct_init.c:27:7:27:16 | call to user_input : void | struct_init.c:31:23:31:23 | a |
|
||||
nodes
|
||||
| A.cpp:126:5:126:5 | ref arg b [c] : void | semmle.label | ref arg b [c] : void |
|
||||
| A.cpp:126:12:126:18 | new : void | semmle.label | new : void |
|
||||
| A.cpp:131:8:131:8 | ref arg b [c] : void | semmle.label | ref arg b [c] : void |
|
||||
| A.cpp:132:10:132:10 | b [c] : void | semmle.label | b [c] : void |
|
||||
| A.cpp:132:10:132:13 | (void *)... | semmle.label | (void *)... |
|
||||
| A.cpp:132:13:132:13 | c | semmle.label | c |
|
||||
| A.cpp:132:13:132:13 | c : void | semmle.label | c : void |
|
||||
| aliasing.cpp:9:3:9:22 | s [post update] : void | semmle.label | s [post update] : void |
|
||||
| aliasing.cpp:9:3:9:22 | s [post update] [m1] : void | semmle.label | s [post update] [m1] : void |
|
||||
| aliasing.cpp:9:11:9:20 | call to user_input : void | semmle.label | call to user_input : void |
|
||||
| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] : void | semmle.label | (reference dereference) [post update] : void |
|
||||
| aliasing.cpp:13:3:13:21 | (reference dereference) [post update] [m1] : void | semmle.label | (reference dereference) [post update] [m1] : void |
|
||||
| aliasing.cpp:13:10:13:19 | call to user_input : void | semmle.label | call to user_input : void |
|
||||
| aliasing.cpp:25:17:25:19 | ref arg & ... [m1] : void | semmle.label | ref arg & ... [m1] : void |
|
||||
| aliasing.cpp:26:19:26:20 | ref arg (reference to) [m1] : void | semmle.label | ref arg (reference to) [m1] : void |
|
||||
| aliasing.cpp:29:8:29:9 | s1 [m1] : void | semmle.label | s1 [m1] : void |
|
||||
| aliasing.cpp:29:11:29:12 | m1 | semmle.label | m1 |
|
||||
| aliasing.cpp:30:8:30:9 | s2 [m1] : void | semmle.label | s2 [m1] : void |
|
||||
| aliasing.cpp:30:11:30:12 | m1 | semmle.label | m1 |
|
||||
| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | semmle.label | (reference dereference) [post update] : void |
|
||||
| aliasing.cpp:37:13:37:22 | call to user_input : void | semmle.label | call to user_input : void |
|
||||
| aliasing.cpp:38:11:38:12 | m1 | semmle.label | m1 |
|
||||
| aliasing.cpp:42:3:42:22 | s2 [post update] : void | semmle.label | s2 [post update] : void |
|
||||
| aliasing.cpp:42:11:42:20 | call to user_input : void | semmle.label | call to user_input : void |
|
||||
| aliasing.cpp:43:13:43:14 | m1 | semmle.label | m1 |
|
||||
| aliasing.cpp:79:3:79:22 | s [post update] : void | semmle.label | s [post update] : void |
|
||||
| aliasing.cpp:79:11:79:20 | call to user_input : void | semmle.label | call to user_input : void |
|
||||
| aliasing.cpp:80:12:80:13 | m1 | semmle.label | m1 |
|
||||
| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | semmle.label | (reference dereference) [post update] : void |
|
||||
| aliasing.cpp:86:10:86:19 | call to user_input : void | semmle.label | call to user_input : void |
|
||||
| aliasing.cpp:87:12:87:13 | m1 | semmle.label | m1 |
|
||||
| aliasing.cpp:92:3:92:23 | s [post update] : void | semmle.label | s [post update] : void |
|
||||
| aliasing.cpp:92:12:92:21 | call to user_input : void | semmle.label | call to user_input : void |
|
||||
| aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 |
|
||||
| struct_init.c:20:20:20:29 | VariableAddress [post update] : void | semmle.label | VariableAddress [post update] : void |
|
||||
| struct_init.c:20:20:20:29 | call to user_input : void | semmle.label | call to user_input : void |
|
||||
| struct_init.c:22:11:22:11 | a | semmle.label | a |
|
||||
| struct_init.c:27:7:27:16 | FieldAddress [post update] : void | semmle.label | FieldAddress [post update] : void |
|
||||
| struct_init.c:27:7:27:16 | call to user_input : void | semmle.label | call to user_input : void |
|
||||
| struct_init.c:31:23:31:23 | a | semmle.label | a |
|
||||
#select
|
||||
| A.cpp:132:10:132:13 | (void *)... | A.cpp:126:12:126:18 | new : void | A.cpp:132:10:132:13 | (void *)... | (void *)... flows from $@ | A.cpp:126:12:126:18 | new : void | new : void |
|
||||
| A.cpp:132:13:132:13 | c | A.cpp:126:12:126:18 | new : void | A.cpp:132:13:132:13 | c | c flows from $@ | A.cpp:126:12:126:18 | new : void | new : void |
|
||||
| aliasing.cpp:29:11:29:12 | m1 | aliasing.cpp:9:11:9:20 | call to user_input : void | aliasing.cpp:29:11:29:12 | m1 | m1 flows from $@ | aliasing.cpp:9:11:9:20 | call to user_input : void | call to user_input : void |
|
||||
| aliasing.cpp:30:11:30:12 | m1 | aliasing.cpp:13:10:13:19 | call to user_input : void | aliasing.cpp:30:11:30:12 | m1 | m1 flows from $@ | aliasing.cpp:13:10:13:19 | call to user_input : void | call to user_input : void |
|
||||
| aliasing.cpp:38:11:38:12 | m1 | aliasing.cpp:37:13:37:22 | call to user_input : void | aliasing.cpp:38:11:38:12 | m1 | m1 flows from $@ | aliasing.cpp:37:13:37:22 | call to user_input : void | call to user_input : void |
|
||||
| aliasing.cpp:43:13:43:14 | m1 | aliasing.cpp:42:11:42:20 | call to user_input : void | aliasing.cpp:43:13:43:14 | m1 | m1 flows from $@ | aliasing.cpp:42:11:42:20 | call to user_input : void | call to user_input : void |
|
||||
| aliasing.cpp:80:12:80:13 | m1 | aliasing.cpp:79:11:79:20 | call to user_input : void | aliasing.cpp:80:12:80:13 | m1 | m1 flows from $@ | aliasing.cpp:79:11:79:20 | call to user_input : void | call to user_input : void |
|
||||
|
||||
Reference in New Issue
Block a user