Skip to content

Commit 72009f8

Browse files
authored
Merge pull request #10085 from smowton/smowton/fix/dont-use-write-instruction-for-channel-flow
Go: don't use WriteNode for channel writes
2 parents ad1cb8f + 3802dea commit 72009f8

File tree

6 files changed

+74
-13
lines changed

6 files changed

+74
-13
lines changed

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

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -166,21 +166,11 @@ module ControlFlow {
166166
)
167167
}
168168

169-
/**
170-
* Holds if this node writes `rhs` to `channel`.
171-
*/
172-
predicate writesToChannel(DataFlow::ExprNode channel, DataFlow::ExprNode rhs) {
173-
exists(SendStmt send |
174-
send.getChannel() = channel.asExpr() and
175-
send.getValue() = rhs.asExpr()
176-
)
177-
}
178-
179169
/**
180170
* Holds if this node sets any field or element of `base` to `rhs`.
181171
*/
182172
predicate writesComponent(DataFlow::Node base, DataFlow::Node rhs) {
183-
writesElement(base, _, rhs) or writesField(base, _, rhs) or writesToChannel(base, rhs)
173+
writesElement(base, _, rhs) or writesField(base, _, rhs)
184174
}
185175
}
186176

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ predicate containerStoreStep(Node node1, Node node2, Content c) {
2424
)
2525
or
2626
c instanceof CollectionContent and
27-
exists(Write w | w.writesToChannel(node2, node1))
27+
exists(SendStmt send |
28+
send.getChannel() = node2.(ExprNode).asExpr() and send.getValue() = node1.(ExprNode).asExpr()
29+
)
2830
or
2931
c instanceof MapKeyContent and
3032
node2.getType() instanceof MapType and

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,10 @@ module Public {
634634
predicate isReceiverOf(MethodDecl m) { parm.isReceiverOf(m) }
635635
}
636636

637-
private Node getADirectlyWrittenNode() { exists(Write w | w.writesComponent(result, _)) }
637+
private Node getADirectlyWrittenNode() {
638+
exists(Write w | w.writesComponent(result, _)) or
639+
result = DataFlow::exprNode(any(SendStmt s).getChannel())
640+
}
638641

639642
private DataFlow::Node getAccessPathPredecessor(DataFlow::Node node) {
640643
result = node.(PointerDereferenceNode).getOperand()
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
edges
2+
| test.go:9:9:9:11 | selection of c [collection] : string | test.go:9:7:9:11 | <-... |
3+
| test.go:13:16:13:16 | definition of s [pointer, c, collection] : string | test.go:16:2:16:2 | s [pointer, c, collection] : string |
4+
| test.go:15:10:15:17 | call to source : string | test.go:16:9:16:12 | data : string |
5+
| test.go:16:2:16:2 | implicit dereference [c, collection] : string | test.go:13:16:13:16 | definition of s [pointer, c, collection] : string |
6+
| test.go:16:2:16:2 | implicit dereference [c, collection] : string | test.go:16:2:16:4 | selection of c [collection] : string |
7+
| test.go:16:2:16:2 | s [pointer, c, collection] : string | test.go:16:2:16:2 | implicit dereference [c, collection] : string |
8+
| test.go:16:2:16:4 | selection of c [collection] : string | test.go:9:9:9:11 | selection of c [collection] : string |
9+
| test.go:16:2:16:4 | selection of c [collection] : string | test.go:16:2:16:2 | implicit dereference [c, collection] : string |
10+
| test.go:16:9:16:12 | data : string | test.go:16:2:16:4 | selection of c [collection] : string |
11+
nodes
12+
| test.go:9:7:9:11 | <-... | semmle.label | <-... |
13+
| test.go:9:9:9:11 | selection of c [collection] : string | semmle.label | selection of c [collection] : string |
14+
| test.go:13:16:13:16 | definition of s [pointer, c, collection] : string | semmle.label | definition of s [pointer, c, collection] : string |
15+
| test.go:15:10:15:17 | call to source : string | semmle.label | call to source : string |
16+
| test.go:16:2:16:2 | implicit dereference [c, collection] : string | semmle.label | implicit dereference [c, collection] : string |
17+
| test.go:16:2:16:2 | s [pointer, c, collection] : string | semmle.label | s [pointer, c, collection] : string |
18+
| test.go:16:2:16:4 | selection of c [collection] : string | semmle.label | selection of c [collection] : string |
19+
| test.go:16:9:16:12 | data : string | semmle.label | data : string |
20+
subpaths
21+
#select
22+
| test.go:15:10:15:17 | call to source : string | test.go:15:10:15:17 | call to source : string | test.go:9:7:9:11 | <-... | path |
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package test
2+
3+
type State struct {
4+
c chan string
5+
}
6+
7+
func handler(s *State) {
8+
9+
sink(<-s.c)
10+
11+
}
12+
13+
func requester(s *State) {
14+
15+
data := source()
16+
s.c <- data
17+
18+
}
19+
20+
func source() string {
21+
22+
return "tainted"
23+
24+
}
25+
26+
func sink(s string) {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import go
2+
import DataFlow::PathGraph
3+
4+
class TestConfig extends DataFlow::Configuration {
5+
TestConfig() { this = "test config" }
6+
7+
override predicate isSource(DataFlow::Node source) {
8+
source.(DataFlow::CallNode).getTarget().getName() = "source"
9+
}
10+
11+
override predicate isSink(DataFlow::Node sink) {
12+
sink = any(DataFlow::CallNode c | c.getTarget().getName() = "sink").getAnArgument()
13+
}
14+
}
15+
16+
from DataFlow::PathNode source, DataFlow::PathNode sink, TestConfig c
17+
where c.hasFlowPath(source, sink)
18+
select source, source, sink, "path"

0 commit comments

Comments
 (0)