Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
22381f3
C++: Demonstrate amount of field flow already present
MathiasVP Mar 24, 2020
a5f08e1
C++: Split parameter node class into an explicit and implicit version
MathiasVP Mar 24, 2020
077c282
C++: Add field flow and accept tests
MathiasVP Mar 24, 2020
f92dd3c
C++: Autoformat
MathiasVP Mar 24, 2020
fbef146
C++: Remove PositionalArgumentWithoutWriteSideEffectNode (since not a…
MathiasVP Mar 26, 2020
c6c6138
C++: Removed toString from PostUpdateNodes. They were more confusing …
MathiasVP Mar 26, 2020
a43abaa
Merge branch 'master' into ir-flow-fields
MathiasVP Mar 26, 2020
580310f
Merge branch 'master' into ir-flow-fields
MathiasVP Mar 27, 2020
5ba5791
C++: Only allow flow through non-conflated chi instructions
MathiasVP Mar 27, 2020
7fce4ce
Include join order fix from #3142
MathiasVP Mar 28, 2020
020c273
Merge branch 'master' into ir-flow-fields
MathiasVP Apr 2, 2020
af9e05b
C++: Accept test
MathiasVP Apr 2, 2020
dda3aaa
C++: Add QLDoc to public classes and predicates
MathiasVP Apr 2, 2020
ce5d8d5
Merge branch 'master' into ir-flow-fields
MathiasVP Apr 2, 2020
317734f
C++: Attach PostUpdateNodes to Chi nodes following aschackmull's sugg…
MathiasVP Apr 5, 2020
3aa2932
C++: Ensure that only non-conflated chi instructions are used everywhere
MathiasVP Apr 6, 2020
c577541
C++: Fix reverse read dataflow consistency failure and accept tests
MathiasVP Apr 6, 2020
5719967
C++: Remove single-field case from PostUpdateNode and accept tests
MathiasVP Apr 7, 2020
d56284f
C++: Move added flow from simpleLocalFlowStep to simpleInstructionLoc…
MathiasVP Apr 7, 2020
52b179a
Merge branch 'master' into ir-flow-fields
MathiasVP Apr 7, 2020
d65c52d
Merge branch 'master' into ir-flow-fields
MathiasVP Apr 8, 2020
7f5330d
Merge branch 'master' into ir-flow-fields
MathiasVP Apr 9, 2020
945ecff
C++: Add charpred to ParameterNode
MathiasVP Apr 13, 2020
daac5c5
Merge branch 'master' into ir-flow-fields
MathiasVP Apr 13, 2020
cde34c9
C++: Accept test output which I previously forgot to accept
MathiasVP Apr 13, 2020
209e084
Merge branch 'master' into ir-flow-fields
MathiasVP Apr 15, 2020
f02feac
C++: Add flow from #3220
MathiasVP Apr 15, 2020
62e2ffe
C++: Make PartialDefinitionNode private and add/update comments based…
MathiasVP Apr 16, 2020
8c03423
C++: Accept test output
MathiasVP Apr 17, 2020
ba0429c
Merge branch 'master' into ir-flow-fields
MathiasVP Apr 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
C++: Remove PositionalArgumentWithoutWriteSideEffectNode (since not a…
…ll arguments need a PostUpdateNode). Also generalized the added flow rule in simpleLocalFlowStep since there isn't always a ChiInstruction - for instance of it's a write to a struct that only has a single field.
  • Loading branch information
MathiasVP committed Mar 26, 2020
commit fbef146a497e492d3cc5deb877c6b0f147421c34
36 changes: 15 additions & 21 deletions cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,17 @@ abstract class PostUpdateNode extends InstructionNode {
override string toString() { result = getPreUpdateNode().toString() + " [post update]" }
}

abstract class PartialDefinitionNode extends PostUpdateNode, TInstructionNode { }
abstract private class PartialDefinitionNode extends PostUpdateNode, TInstructionNode {
final Instruction getInstructionOrChi() {
exists(ChiInstruction chi |
// TODO: This should be a non-conflated ChiInstruction once #3123 is merged
chi.getPartial() = getInstruction() and
result = chi
)
or
result = getInstruction()
}
}

class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
override StoreInstruction instr;
Expand Down Expand Up @@ -268,22 +278,6 @@ class DefinitionByReferenceNode extends PartialDefinitionNode {
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() }
}

/**
* A `Node` corresponding to a variable in the program, as opposed to the
* value of that variable at some particular point. This can be used for
Expand Down Expand Up @@ -365,10 +359,10 @@ 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
exists(LoadInstruction load |
// TODO: These can probably be getSourceValue() after #3112 is merged
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's now merged (that's the line I meant to comment on a minute ago).

Copy link
Copy Markdown
Contributor Author

@MathiasVP MathiasVP Mar 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sadly my comment turned out to be incorrect. The flow in the following program is not captured by only following exact Chi operands:

void sink(int *o);

struct B
{
  int *c;
  void set(int *c) { this->c = c; }
};

void f7(B *b)
{
  b->set(new int);
}

void f8()
{
  B *b = new B();
  f7(b);
  sink(b->c); // flow
}

since the load on b->c only is a total overlap.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then you'll want to merge #3097 and use isResultConflated here.

load.getSourceValueOperand().getAnyDef() =
nodeFrom.(PartialDefinitionNode).getInstructionOrChi() and
nodeTo.asInstruction() = load.getSourceAddress().(FieldAddressInstruction).getObjectAddress()
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can move this case into simpleInstructionLocalFlowStep. That will save you two asInstruction calls, and it will make this code cached when #3189 is merged.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've done this now in d56284f. This case I've added in simpleInstructionLocalFlowStep has an obvious generalization, which we might add at some later stage. But I think that deserves its own investigation first.

}
Expand Down
35 changes: 35 additions & 0 deletions cpp/ql/test/library-tests/dataflow/fields/ir-flow.expected
Original file line number Diff line number Diff line change
Expand Up @@ -15,27 +15,48 @@ edges
| 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:37:3:37:24 | (reference dereference) [post update] [m1] : void |
| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] : void | aliasing.cpp:38:11:38:12 | m1 |
| aliasing.cpp:37:3:37:24 | (reference dereference) [post update] [m1] : void | aliasing.cpp:38:8:38:9 | s1 [m1] : void |
| 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:38:8:38:9 | s1 [m1] : void | aliasing.cpp:38:11:38:12 | m1 |
| aliasing.cpp:42:3:42:22 | s2 [post update] : void | aliasing.cpp:42:3:42:22 | s2 [post update] [m1] : void |
| aliasing.cpp:42:3:42:22 | s2 [post update] : void | aliasing.cpp:43:13:43:14 | m1 |
| aliasing.cpp:42:3:42:22 | s2 [post update] [m1] : void | aliasing.cpp:43:8:43:11 | (reference dereference) [m1] : void |
| 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:43:8:43:11 | (reference dereference) [m1] : void | aliasing.cpp:43:13:43:14 | m1 |
| aliasing.cpp:79:3:79:22 | s [post update] : void | aliasing.cpp:79:3:79:22 | s [post update] [m1] : void |
| aliasing.cpp:79:3:79:22 | s [post update] : void | aliasing.cpp:80:12:80:13 | m1 |
| aliasing.cpp:79:3:79:22 | s [post update] [m1] : void | aliasing.cpp:80:10:80:10 | s [m1] : void |
| 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:80:10:80:10 | s [m1] : void | aliasing.cpp:80:12:80:13 | m1 |
| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | aliasing.cpp:86:3:86:21 | (reference dereference) [post update] [m1] : void |
| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] : void | aliasing.cpp:87:12:87:13 | m1 |
| aliasing.cpp:86:3:86:21 | (reference dereference) [post update] [m1] : void | aliasing.cpp:87:10:87:10 | s [m1] : void |
| 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:87:10:87:10 | s [m1] : void | aliasing.cpp:87:12:87:13 | m1 |
| aliasing.cpp:92:3:92:23 | s [post update] : void | aliasing.cpp:92:3:92:23 | s [post update] [m1] : void |
| aliasing.cpp:92:3:92:23 | s [post update] : void | aliasing.cpp:93:12:93:13 | m1 |
| aliasing.cpp:92:3:92:23 | s [post update] [m1] : void | aliasing.cpp:93:10:93:10 | s [m1] : void |
| 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 |
| aliasing.cpp:93:10:93:10 | s [m1] : void | aliasing.cpp:93:12:93:13 | m1 |
| struct_init.c:20:20:20:29 | VariableAddress [post update] : void | struct_init.c:20:20:20:29 | VariableAddress [post update] [a] : void |
| 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 | VariableAddress [post update] [a] : void | struct_init.c:22:8:22:9 | ab [a] : void |
| 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:22:8:22:9 | ab [a] : void | struct_init.c:22:11:22:11 | a |
| struct_init.c:27:7:27:16 | FieldAddress [post update] : void | struct_init.c:27:7:27:16 | FieldAddress [post update] [a] : void |
| 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 | FieldAddress [post update] [a] : void | struct_init.c:31:14:31:21 | nestedAB [a] : void |
| 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 |
| struct_init.c:31:14:31:21 | nestedAB [a] : 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 |
Expand All @@ -57,25 +78,39 @@ nodes
| 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:3:37:24 | (reference dereference) [post update] [m1] : void | semmle.label | (reference dereference) [post update] [m1] : void |
| aliasing.cpp:37:13:37:22 | call to user_input : void | semmle.label | call to user_input : void |
| aliasing.cpp:38:8:38:9 | s1 [m1] : void | semmle.label | s1 [m1] : 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:3:42:22 | s2 [post update] [m1] : void | semmle.label | s2 [post update] [m1] : void |
| aliasing.cpp:42:11:42:20 | call to user_input : void | semmle.label | call to user_input : void |
| aliasing.cpp:43:8:43:11 | (reference dereference) [m1] : void | semmle.label | (reference dereference) [m1] : 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:3:79:22 | s [post update] [m1] : void | semmle.label | s [post update] [m1] : void |
| aliasing.cpp:79:11:79:20 | call to user_input : void | semmle.label | call to user_input : void |
| aliasing.cpp:80:10:80:10 | s [m1] : void | semmle.label | s [m1] : 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:3:86:21 | (reference dereference) [post update] [m1] : void | semmle.label | (reference dereference) [post update] [m1] : void |
| aliasing.cpp:86:10:86:19 | call to user_input : void | semmle.label | call to user_input : void |
| aliasing.cpp:87:10:87:10 | s [m1] : void | semmle.label | s [m1] : 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:3:92:23 | s [post update] [m1] : void | semmle.label | s [post update] [m1] : void |
| aliasing.cpp:92:12:92:21 | call to user_input : void | semmle.label | call to user_input : void |
| aliasing.cpp:93:10:93:10 | s [m1] : void | semmle.label | s [m1] : 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 | VariableAddress [post update] [a] : void | semmle.label | VariableAddress [post update] [a] : void |
| struct_init.c:20:20:20:29 | call to user_input : void | semmle.label | call to user_input : void |
| struct_init.c:22:8:22:9 | ab [a] : void | semmle.label | ab [a] : 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 | FieldAddress [post update] [a] : void | semmle.label | FieldAddress [post update] [a] : void |
| struct_init.c:27:7:27:16 | call to user_input : void | semmle.label | call to user_input : void |
| struct_init.c:31:14:31:21 | nestedAB [a] : void | semmle.label | nestedAB [a] : 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 |
Expand Down