Skip to content

Commit 4843d1c

Browse files
committed
Change post-update nodes
1 parent 7cd9109 commit 4843d1c

File tree

3 files changed

+94
-31
lines changed

3 files changed

+94
-31
lines changed

go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ module ControlFlow {
135135
exists(IR::FieldTarget trg | trg = super.getLhs() |
136136
(
137137
trg.getBase() = base.asInstruction() or
138-
trg.getBase() = MkImplicitDeref(base.asExpr())
138+
trg.getBase() = IR::implicitDerefInstruction(base.asExpr())
139139
) and
140140
trg.getField() = f and
141141
super.getRhs() = rhs.asInstruction()
@@ -155,7 +155,7 @@ module ControlFlow {
155155
exists(IR::ElementTarget trg | trg = super.getLhs() |
156156
(
157157
trg.getBase() = base.asInstruction() or
158-
trg.getBase() = MkImplicitDeref(base.asExpr())
158+
trg.getBase() = IR::implicitDerefInstruction(base.asExpr())
159159
) and
160160
trg.getIndex() = index.asInstruction() and
161161
super.getRhs() = rhs.asInstruction()

go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll

Lines changed: 78 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,54 @@ private newtype TNode =
1111
MkSsaNode(SsaDefinition ssa) or
1212
MkGlobalFunctionNode(Function f) or
1313
MkImplicitVarargsSlice(CallExpr c) { c.hasImplicitVarargs() } or
14-
MkFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn)
14+
MkFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
15+
MkPostUpdateNode(IR::Instruction insn) { insn = updatedInstruction() }
16+
17+
private IR::Instruction getADirectlyWrittenInstruction() {
18+
exists(IR::WriteTarget target, IR::Instruction base |
19+
target = any(IR::WriteInstruction w).getLhs() and
20+
(base = result or base = IR::implicitDerefInstruction(result.(IR::EvalInstruction).getExpr()))
21+
|
22+
target.(IR::FieldTarget).getBase() = base or
23+
target.(IR::ElementTarget).getBase() = base
24+
)
25+
or
26+
result = IR::evalExprInstruction(any(SendStmt s).getChannel())
27+
}
28+
29+
private IR::Instruction getAccessPathPredecessor2(IR::Instruction insn) {
30+
exists(Expr e | result = IR::evalExprInstruction(e) |
31+
e = insn.(IR::EvalInstruction).getExpr().(UnaryExpr).getOperand()
32+
or
33+
e = insn.(IR::EvalInstruction).getExpr().(StarExpr).getBase()
34+
or
35+
e = insn.(IR::EvalImplicitDerefInstruction).getOperand()
36+
)
37+
or
38+
result = insn.(IR::ComponentReadInstruction).getBase()
39+
}
40+
41+
private IR::Instruction getAWrittenInstruction() {
42+
result = getAccessPathPredecessor2*(getADirectlyWrittenInstruction())
43+
}
44+
45+
private IR::Instruction updatedInstruction() {
46+
result = IR::evalExprInstruction(updatedExpr()) or
47+
result instanceof IR::EvalImplicitDerefInstruction or
48+
result = getAWrittenInstruction()
49+
}
50+
51+
private Expr updatedExpr() {
52+
result instanceof AddressExpr
53+
or
54+
result = any(AddressExpr e).getOperand()
55+
or
56+
result instanceof StarExpr
57+
or
58+
result instanceof DerefExpr
59+
or
60+
result = any(CallExpr ce).getAnArgument() and mutableType(result.getType())
61+
}
1562

1663
/** Nodes intended for only use inside the data-flow libraries. */
1764
module Private {
@@ -734,6 +781,10 @@ module Public {
734781
)
735782
}
736783

784+
private class UpdateNode extends InstructionNode {
785+
UpdateNode() { insn = updatedInstruction() }
786+
}
787+
737788
/**
738789
* A node associated with an object after an operation that might have
739790
* changed its state.
@@ -753,35 +804,35 @@ module Public {
753804
abstract Node getPreUpdateNode();
754805
}
755806

756-
private class DefaultPostUpdateNode extends PostUpdateNode {
757-
Node preupd;
807+
class DefaultPostUpdateNode extends PostUpdateNode {
808+
UpdateNode preupd;
758809

759-
DefaultPostUpdateNode() {
760-
(
761-
preupd instanceof AddressOperationNode
762-
or
763-
preupd = any(AddressOperationNode addr).getOperand()
764-
or
765-
preupd = any(PointerDereferenceNode deref).getOperand()
766-
or
767-
preupd = getAWrittenNode()
768-
or
769-
(
770-
preupd instanceof ArgumentNode and not preupd instanceof ImplicitVarargsSlice
771-
or
772-
preupd = any(CallNode c).getAnImplicitVarargsArgument()
773-
) and
774-
mutableType(preupd.getType())
775-
) and
776-
(
777-
preupd = this.(SsaNode).getAUse()
778-
or
779-
preupd = this and
780-
not basicLocalFlowStep(_, this)
781-
)
782-
}
810+
DefaultPostUpdateNode() { this = MkPostUpdateNode(preupd.asInstruction()) }
783811

784812
override Node getPreUpdateNode() { result = preupd }
813+
814+
Node getSuccessor() {
815+
preupd = result.(SsaNode).getAUse()
816+
or
817+
preupd = result and
818+
not basicLocalFlowStep0(_, preupd)
819+
}
820+
821+
override ControlFlow::Root getRoot() { result = preupd.asInstruction().getRoot() }
822+
823+
override Type getType() { result = preupd.asInstruction().getResultType() }
824+
825+
override string getNodeKind() { result = "post-update node" }
826+
827+
override string toString() {
828+
result = "post-update node for " + preupd.asInstruction().toString()
829+
}
830+
831+
override predicate hasLocationInfo(
832+
string filepath, int startline, int startcolumn, int endline, int endcolumn
833+
) {
834+
preupd.asInstruction().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
835+
}
785836
}
786837

787838
/**

go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,10 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
4141

4242
/**
4343
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
44-
* (intra-procedural) step, not taking function models into account.
44+
* (intra-procedural) step, not taking function models into account, and also
45+
* excluding flow from post-update nodes to their successors.
4546
*/
46-
predicate basicLocalFlowStep(Node nodeFrom, Node nodeTo) {
47+
predicate basicLocalFlowStep0(Node nodeFrom, Node nodeTo) {
4748
// Instruction -> Instruction
4849
exists(Expr pred, Expr succ |
4950
succ.(LogicalBinaryExpr).getAnOperand() = pred or
@@ -89,6 +90,17 @@ predicate basicLocalFlowStep(Node nodeFrom, Node nodeTo) {
8990
any(GlobalFunctionNode fn | fn.getFunction() = nodeTo.asExpr().(FunctionName).getTarget())
9091
}
9192

93+
/**
94+
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
95+
* (intra-procedural) step, not taking function models into account.
96+
*/
97+
predicate basicLocalFlowStep(Node nodeFrom, Node nodeTo) {
98+
basicLocalFlowStep0(nodeFrom, nodeTo)
99+
or
100+
// post-update node -> successor
101+
nodeTo = nodeFrom.(DefaultPostUpdateNode).getSuccessor()
102+
}
103+
92104
pragma[noinline]
93105
private Field getASparselyUsedChannelTypedField() {
94106
result.getType() instanceof ChanType and

0 commit comments

Comments
 (0)