Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
208 changes: 200 additions & 8 deletions ql/src/semmle/go/frameworks/Stdlib.qll
Original file line number Diff line number Diff line change
Expand Up @@ -122,28 +122,220 @@ module Fmt {
}

/** Provides models of commonly used functions in the `io` package. */
module Io {
module IO {
private class Copy extends TaintTracking::FunctionModel, Function {
Copy() {
// func Copy(dst Writer, src Reader) (written int64, err error)
// func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error)
// func CopyN(dst Writer, src Reader, n int64) (written int64, err error)
hasQualifiedName("io", "Copy") or
hasQualifiedName("io", "CopyBuffer") or
hasQualifiedName("io", "CopyN")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(1) and output.isParameter(0)
}
}

private class Pipe extends TaintTracking::FunctionModel, Function {
Pipe() {
// func Pipe() (*PipeReader, *PipeWriter)
hasQualifiedName("io", "Pipe")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isResult(0) and output.isResult(1)
}
}

private class IORead extends TaintTracking::FunctionModel, Function {
IORead() {
// func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)
// func ReadFull(r Reader, buf []byte) (n int, err error)
hasQualifiedName("io", "ReadAtLeast") or
hasQualifiedName("io", "ReadFull")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and output.isParameter(1)
}
}

private class WriteString extends TaintTracking::FunctionModel {
WriteString() {
// func WriteString(w Writer, s string) (n int, err error)
this.hasQualifiedName("io", "WriteString")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(1) and output.isParameter(0)
}
}

private class ByteReaderReadByte extends TaintTracking::FunctionModel, Method {
ByteReaderReadByte() {
// ReadByte() (byte, error)
this.implements("io", "ByteReader", "ReadByte")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isReceiver() and output.isResult(0)
}
}

private class ByteWriterWriteByte extends TaintTracking::FunctionModel, Method {
ByteWriterWriteByte() {
// WriteByte(c byte) error
this.implements("io", "ByteWriter", "WriteByte")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and output.isReceiver()
}
}

private class ReaderRead extends TaintTracking::FunctionModel, Method {
ReaderRead() { this.implements("io", "Reader", "Read") }
ReaderRead() {
// Read(p []byte) (n int, err error)
this.implements("io", "Reader", "Read")
}

override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) {
inp.isReceiver() and outp.isParameter(0)
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isReceiver() and output.isParameter(0)
}
}

private class LimitReader extends TaintTracking::FunctionModel, Function {
LimitReader() {
// func LimitReader(r Reader, n int64) Reader
this.hasQualifiedName("io", "LimitReader")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and output.isResult()
}
}

private class MultiReader extends TaintTracking::FunctionModel, Function {
MultiReader() {
// func MultiReader(readers ...Reader) Reader
this.hasQualifiedName("io", "MultiReader")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(_) and output.isResult()
}
}

private class TeeReader extends TaintTracking::FunctionModel, Function {
TeeReader() {
// func TeeReader(r Reader, w Writer) Reader
this.hasQualifiedName("io", "TeeReader")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and output.isResult()
or
input.isParameter(0) and output.isParameter(1)
}
}

private class ReaderAtReadAt extends TaintTracking::FunctionModel, Method {
ReaderAtReadAt() { this.implements("io", "ReaderAt", "ReadAt") }

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
// ReadAt(p []byte, off int64) (n int, err error)
input.isReceiver() and output.isParameter(0)
}
}

private class ReaderFromReadFrom extends TaintTracking::FunctionModel, Method {
ReaderFromReadFrom() {
// ReadFrom(r Reader) (n int64, err error)
this.implements("io", "ReaderFrom", "ReadFrom")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and output.isReceiver()
}
}

private class RuneReaderReadRune extends TaintTracking::FunctionModel, Method {
RuneReaderReadRune() {
// ReadRune() (r rune, size int, err error)
this.implements("io", "RuneReader", "ReadRune")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isReceiver() and output.isResult(0)
}
}

private class NewSectionReader extends TaintTracking::FunctionModel, Function {
NewSectionReader() {
// func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader
this.hasQualifiedName("io", "NewSectionReader")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and output.isResult()
}
}

// A Taint Model for the stdlib io StringWriter interface
private class StringWriterWriteString extends TaintTracking::FunctionModel, Method {
StringWriterWriteString() {
// WriteString(s string) (n int, err error)
this.implements("io", "StringWriter", "WriteString")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and output.isReceiver()
}
}

private class WriterWrite extends TaintTracking::FunctionModel, Method {
WriterWrite() { this.implements("io", "Writer", "Write") }
WriterWrite() {
// Write(p []byte) (n int, err error)
this.implements("io", "Writer", "Write")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and output.isReceiver()
}
}

private class WriteString extends TaintTracking::FunctionModel {
WriteString() { this.hasQualifiedName("io", "WriteString") }
private class MultiWriter extends TaintTracking::FunctionModel, Function {
MultiWriter() {
// func MultiWriter(writers ...Writer) Writer
hasQualifiedName("io", "MultiWriter")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(1) and output.isParameter(0)
input.isResult() and output.isParameter(_)
}
}

private class WriterAtWriteAt extends TaintTracking::FunctionModel, Method {
WriterAtWriteAt() {
// WriteAt(p []byte, off int64) (n int, err error)
this.implements("io", "WriterAt", "WriteAt")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isParameter(0) and output.isReceiver()
}
}

private class WriterToWriteTo extends TaintTracking::FunctionModel, Method {
WriterToWriteTo() {
// WriteTo(w Writer) (n int64, err error)
this.implements("io", "WriterTo", "WriteTo")
}

override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
input.isReceiver() and output.isParameter(0)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,54 @@
| crypto.go:11:18:11:57 | call to Open | crypto.go:11:2:11:57 | ... := ...[0] |
| crypto.go:11:18:11:57 | call to Open | crypto.go:11:2:11:57 | ... := ...[1] |
| crypto.go:11:42:11:51 | ciphertext | crypto.go:11:2:11:57 | ... := ...[0] |
| io.go:15:3:15:3 | definition of w | io.go:15:23:15:27 | &... |
| io.go:15:3:15:3 | definition of w | io.go:15:30:15:34 | &... |
| io.go:15:23:15:27 | &... | io.go:14:7:14:10 | definition of buf1 |
| io.go:15:24:15:27 | buf1 | io.go:15:23:15:27 | &... |
| io.go:15:30:15:34 | &... | io.go:14:13:14:16 | definition of buf2 |
| io.go:15:31:15:34 | buf2 | io.go:15:30:15:34 | &... |
| io.go:17:14:17:19 | reader | io.go:15:3:15:3 | definition of w |
| io.go:24:19:24:23 | &... | io.go:22:7:22:10 | definition of buf1 |
| io.go:24:20:24:23 | buf1 | io.go:24:19:24:23 | &... |
| io.go:26:21:26:26 | reader | io.go:24:3:24:4 | definition of w2 |
| io.go:32:19:32:23 | &... | io.go:31:7:31:10 | definition of buf1 |
| io.go:32:20:32:23 | buf1 | io.go:32:19:32:23 | &... |
| io.go:34:16:34:21 | reader | io.go:32:3:32:4 | definition of w2 |
| io.go:38:3:38:3 | definition of r | io.go:38:3:38:19 | ... := ...[1] |
| io.go:38:11:38:19 | call to Pipe | io.go:38:3:38:19 | ... := ...[0] |
| io.go:38:11:38:19 | call to Pipe | io.go:38:3:38:19 | ... := ...[1] |
| io.go:39:17:39:31 | "some string\\n" | io.go:38:6:38:6 | definition of w |
| io.go:42:16:42:16 | r | io.go:41:3:41:5 | definition of buf |
| io.go:43:13:43:15 | buf | io.go:43:13:43:24 | call to String |
| io.go:49:18:49:23 | reader | io.go:48:3:48:5 | definition of buf |
| io.go:55:15:55:20 | reader | io.go:54:3:54:5 | definition of buf |
| io.go:60:18:60:21 | &... | io.go:59:7:59:9 | definition of buf |
| io.go:60:19:60:21 | buf | io.go:60:18:60:21 | &... |
| io.go:61:21:61:26 | "test" | io.go:60:3:60:3 | definition of w |
| io.go:66:11:66:16 | reader | io.go:66:3:66:27 | ... := ...[0] |
| io.go:66:11:66:27 | call to ReadByte | io.go:66:3:66:27 | ... := ...[0] |
| io.go:66:11:66:27 | call to ReadByte | io.go:66:3:66:27 | ... := ...[1] |
| io.go:68:21:68:21 | t | io.go:67:7:67:13 | definition of bwriter |
| io.go:74:3:74:8 | reader | io.go:73:3:73:5 | definition of buf |
| io.go:79:3:79:8 | reader | io.go:78:3:78:5 | definition of buf |
| io.go:84:24:84:29 | reader | io.go:84:9:84:33 | call to LimitReader |
| io.go:85:22:85:23 | lr | io.go:85:11:85:19 | selection of Stdout |
| io.go:92:23:92:24 | r1 | io.go:92:8:92:33 | call to MultiReader |
| io.go:92:27:92:28 | r2 | io.go:92:8:92:33 | call to MultiReader |
| io.go:92:31:92:32 | r3 | io.go:92:8:92:33 | call to MultiReader |
| io.go:93:22:93:22 | r | io.go:93:11:93:19 | selection of Stdout |
| io.go:98:23:98:23 | r | io.go:98:10:98:30 | call to TeeReader |
| io.go:98:23:98:23 | r | io.go:98:26:98:29 | &... |
| io.go:98:26:98:29 | &... | io.go:97:7:97:9 | definition of buf |
| io.go:98:27:98:29 | buf | io.go:98:26:98:29 | &... |
| io.go:100:22:100:24 | tee | io.go:100:11:100:19 | selection of Stdout |
| io.go:104:28:104:28 | r | io.go:104:8:104:36 | call to NewSectionReader |
| io.go:105:22:105:22 | s | io.go:105:11:105:19 | selection of Stdout |
| io.go:109:16:109:16 | r | io.go:109:3:109:27 | ... := ...[0] |
| io.go:109:16:109:27 | call to ReadRune | io.go:109:3:109:27 | ... := ...[0] |
| io.go:109:16:109:27 | call to ReadRune | io.go:109:3:109:27 | ... := ...[1] |
| io.go:109:16:109:27 | call to ReadRune | io.go:109:3:109:27 | ... := ...[2] |
| io.go:114:3:114:3 | r | io.go:114:13:114:21 | selection of Stdout |
| main.go:11:12:11:26 | call to Marshal | main.go:11:2:11:26 | ... := ...[0] |
| main.go:11:12:11:26 | call to Marshal | main.go:11:2:11:26 | ... := ...[1] |
| main.go:11:25:11:25 | v | main.go:11:2:11:26 | ... := ...[0] |
Expand Down
Loading