mirror of
https://github.com/github/codeql.git
synced 2026-01-29 14:23:03 +01:00
Merge pull request #131 from porcupineyhairs/IO
Model stdlib's IO package.
This commit is contained in:
@@ -122,28 +122,220 @@ module Fmt {
|
||||
}
|
||||
|
||||
/** Provides models of commonly used functions in the `io` package. */
|
||||
module Io {
|
||||
private class ReaderRead extends TaintTracking::FunctionModel, Method {
|
||||
ReaderRead() { this.implements("io", "Reader", "Read") }
|
||||
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 inp, FunctionOutput outp) {
|
||||
inp.isReceiver() and outp.isParameter(0)
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameter(1) and output.isParameter(0)
|
||||
}
|
||||
}
|
||||
|
||||
private class WriterWrite extends TaintTracking::FunctionModel, Method {
|
||||
WriterWrite() { this.implements("io", "Writer", "Write") }
|
||||
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 WriteString extends TaintTracking::FunctionModel {
|
||||
WriteString() { this.hasQualifiedName("io", "WriteString") }
|
||||
private class ReaderRead extends TaintTracking::FunctionModel, Method {
|
||||
ReaderRead() {
|
||||
// Read(p []byte) (n int, err error)
|
||||
this.implements("io", "Reader", "Read")
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
input.isParameter(1) and output.isParameter(0)
|
||||
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() {
|
||||
// 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 MultiWriter extends TaintTracking::FunctionModel, Function {
|
||||
MultiWriter() {
|
||||
// func MultiWriter(writers ...Writer) Writer
|
||||
hasQualifiedName("io", "MultiWriter")
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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] |
|
||||
|
||||
117
ql/test/library-tests/semmle/go/frameworks/TaintSteps/io.go
Normal file
117
ql/test/library-tests/semmle/go/frameworks/TaintSteps/io.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func io2() {
|
||||
{
|
||||
reader := strings.NewReader("some string")
|
||||
var buf1, buf2 bytes.Buffer
|
||||
w := io.MultiWriter(&buf1, &buf2)
|
||||
|
||||
io.Copy(w, reader)
|
||||
}
|
||||
|
||||
{
|
||||
reader := strings.NewReader("some string")
|
||||
var buf1 bytes.Buffer
|
||||
buf := make([]byte, 512)
|
||||
w2 := io.Writer(&buf1)
|
||||
|
||||
io.CopyBuffer(w2, reader, buf)
|
||||
}
|
||||
|
||||
{
|
||||
reader := strings.NewReader("some string")
|
||||
var buf1 bytes.Buffer
|
||||
w2 := io.Writer(&buf1)
|
||||
|
||||
io.CopyN(w2, reader, 512)
|
||||
}
|
||||
|
||||
{
|
||||
r, w := io.Pipe()
|
||||
fmt.Fprint(w, "some string\n")
|
||||
|
||||
buf := new(bytes.Buffer)
|
||||
buf.ReadFrom(r)
|
||||
fmt.Print(buf.String())
|
||||
}
|
||||
|
||||
{
|
||||
reader := strings.NewReader("some string")
|
||||
buf := make([]byte, 512)
|
||||
io.ReadAtLeast(reader, buf, 512)
|
||||
}
|
||||
|
||||
{
|
||||
reader := strings.NewReader("some string")
|
||||
buf := make([]byte, 512)
|
||||
io.ReadFull(reader, buf)
|
||||
}
|
||||
|
||||
{
|
||||
var buf bytes.Buffer
|
||||
w := io.Writer(&buf)
|
||||
io.WriteString(w, "test")
|
||||
}
|
||||
|
||||
{
|
||||
reader := strings.NewReader("some string")
|
||||
t, _ := reader.ReadByte()
|
||||
var bwriter io.ByteWriter
|
||||
bwriter.WriteByte(t)
|
||||
}
|
||||
|
||||
{
|
||||
reader := strings.NewReader("some string")
|
||||
buf := make([]byte, 512)
|
||||
reader.Read(buf)
|
||||
}
|
||||
{
|
||||
reader := strings.NewReader("some string")
|
||||
buf := make([]byte, 512)
|
||||
reader.ReadAt(buf, 10)
|
||||
}
|
||||
|
||||
{
|
||||
reader := strings.NewReader("some string")
|
||||
lr := io.LimitReader(reader, 4)
|
||||
io.Copy(os.Stdout, lr)
|
||||
}
|
||||
|
||||
{
|
||||
r1 := strings.NewReader("reader1 ")
|
||||
r2 := strings.NewReader("reader2 ")
|
||||
r3 := strings.NewReader("reader3")
|
||||
r := io.MultiReader(r1, r2, r3)
|
||||
io.Copy(os.Stdout, r)
|
||||
}
|
||||
{
|
||||
r := strings.NewReader("some string")
|
||||
var buf bytes.Buffer
|
||||
tee := io.TeeReader(r, &buf)
|
||||
|
||||
io.Copy(os.Stdout, tee)
|
||||
}
|
||||
{
|
||||
r := strings.NewReader("some string")
|
||||
s := io.NewSectionReader(r, 5, 17)
|
||||
io.Copy(os.Stdout, s)
|
||||
}
|
||||
{
|
||||
r := strings.NewReader("some string")
|
||||
run, _, _ := r.ReadRune()
|
||||
fmt.Println(run)
|
||||
}
|
||||
{
|
||||
r := strings.NewReader("some string")
|
||||
r.WriteTo(os.Stdout)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user