Merge pull request #122 from max-schaefer/receiver-output

Fix `getExitNode` for receiver outputs.
This commit is contained in:
Sauyon Lee
2020-04-29 01:25:43 -07:00
committed by GitHub
9 changed files with 45 additions and 13 deletions

View File

@@ -4,6 +4,7 @@
*/
import go
private import semmle.go.dataflow.internal.DataFlowPrivate
/**
* An abstract representation of an input to a function, which is either a parameter
@@ -181,8 +182,8 @@ private class OutParameter extends FunctionOutput, TOutParameter {
}
override DataFlow::Node getExitNode(DataFlow::CallNode c) {
exists(DataFlow::ArgumentNode arg |
arg.argumentOf(c.asExpr(), index) and
exists(DataFlow::Node arg |
arg = getArgument(c, index) and
result.(DataFlow::PostUpdateNode).getPreUpdateNode() = arg
)
}

View File

@@ -272,3 +272,14 @@ predicate isUnreachableInCall(Node n, DataFlowCall call) {
}
int accessPathLimit() { result = 5 }
/**
* Gets the `i`th argument of call `c`, where the receiver of a method call
* counts as argument -1.
*/
Node getArgument(CallNode c, int i) {
result = c.getArgument(i)
or
result = c.(MethodCallNode).getReceiver() and
i = -1
}

View File

@@ -4,6 +4,7 @@
import go
import semmle.go.dataflow.FunctionInputsAndOutputs
private import DataFlowPrivate
cached
private newtype TNode =
@@ -423,17 +424,6 @@ class PostUpdateNode extends Node {
Node getPreUpdateNode() { result = preupd }
}
/**
* Gets the `i`th argument of call `c`, where the receiver of a method call
* counts as argument -1.
*/
private Node getArgument(CallNode c, int i) {
result = c.getArgument(i)
or
result = c.(MethodCallNode).getReceiver() and
i = -1
}
/**
* A data-flow node that occurs as an argument in a call, including receiver arguments.
*/

View File

@@ -2,6 +2,7 @@
| parameter 0 | main.go:53:2:53:22 | call to op2 | main.go:53:6:53:8 | "-" |
| parameter 0 | main.go:55:2:55:27 | call to Printf | main.go:55:13:55:20 | "%d, %d" |
| parameter 0 | main.go:57:2:57:27 | call to Printf | main.go:57:13:57:20 | "%d, %d" |
| parameter 0 | tst.go:10:2:10:29 | call to ReadFrom | tst.go:10:23:10:28 | reader |
| parameter 1 | main.go:51:2:51:14 | call to op | main.go:51:10:51:10 | 1 |
| parameter 1 | main.go:53:2:53:22 | call to op2 | main.go:53:11:53:11 | 2 |
| parameter 1 | main.go:55:2:55:27 | call to Printf | main.go:55:23:55:23 | x |
@@ -11,3 +12,4 @@
| parameter 2 | main.go:55:2:55:27 | call to Printf | main.go:55:26:55:26 | y |
| parameter 2 | main.go:57:2:57:27 | call to Printf | main.go:57:26:57:26 | y |
| receiver | main.go:53:14:53:21 | call to bump | main.go:53:14:53:14 | c |
| receiver | tst.go:10:2:10:29 | call to ReadFrom | tst.go:10:2:10:12 | bytesBuffer |

View File

@@ -1,6 +1,7 @@
| parameter 0 | main.go:5:1:11:1 | function declaration | main.go:5:9:5:10 | definition of op |
| parameter 0 | main.go:13:1:20:1 | function declaration | main.go:13:10:13:11 | definition of op |
| parameter 0 | main.go:40:1:48:1 | function declaration | main.go:40:12:40:12 | definition of b |
| parameter 0 | tst.go:8:1:11:1 | function declaration | tst.go:8:12:8:17 | definition of reader |
| parameter 1 | main.go:5:1:11:1 | function declaration | main.go:5:20:5:20 | definition of x |
| parameter 1 | main.go:13:1:20:1 | function declaration | main.go:13:21:13:21 | definition of x |
| parameter 2 | main.go:5:1:11:1 | function declaration | main.go:5:27:5:27 | definition of y |

View File

@@ -0,0 +1 @@
| file://:0:0:0:0 | ReadFrom | tst.go:10:23:10:28 | reader | tst.go:9:2:9:12 | definition of bytesBuffer |

View File

@@ -0,0 +1,13 @@
import go
class BytesReadFrom extends TaintTracking::FunctionModel, Method {
BytesReadFrom() { this.(Method).hasQualifiedName("bytes", "Buffer", "ReadFrom") }
override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) {
inp.isParameter(0) and outp.isReceiver()
}
}
from Function fn, DataFlow::Node pred, DataFlow::Node succ
where TaintTracking::functionModelStep(fn, pred, succ)
select fn, pred, succ

View File

@@ -1,6 +1,8 @@
| receiver | tst.go:10:2:10:29 | call to ReadFrom | tst.go:9:2:9:12 | definition of bytesBuffer |
| result | main.go:51:2:51:14 | call to op | main.go:51:2:51:14 | call to op |
| result | main.go:53:2:53:22 | call to op2 | main.go:53:2:53:22 | call to op2 |
| result | main.go:53:14:53:21 | call to bump | main.go:53:14:53:21 | call to bump |
| result | tst.go:9:17:9:33 | call to new | tst.go:9:17:9:33 | call to new |
| result 0 | main.go:54:10:54:15 | call to test | main.go:54:2:54:15 | ... := ...[0] |
| result 0 | main.go:56:9:56:15 | call to test2 | main.go:56:2:56:15 | ... = ...[0] |
| result 1 | main.go:54:10:54:15 | call to test | main.go:54:2:54:15 | ... := ...[1] |

View File

@@ -0,0 +1,11 @@
package main
import (
"bytes"
"io"
)
func test4(reader io.Reader) {
bytesBuffer := new(bytes.Buffer)
bytesBuffer.ReadFrom(reader)
}