Skip to content
This repository was archived by the owner on Jan 5, 2023. It is now read-only.

Commit 4e409aa

Browse files
authored
Merge pull request #274 from gagliardetto/standard-lib-pt-2
Add taint tracking for bufio and bytes packages
2 parents b057cbe + df71f0b commit 4e409aa

File tree

5 files changed

+1203
-22
lines changed

5 files changed

+1203
-22
lines changed

ql/src/semmle/go/frameworks/Stdlib.qll

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
import go
66
import semmle.go.frameworks.stdlib.ArchiveTar
77
import semmle.go.frameworks.stdlib.ArchiveZip
8+
import semmle.go.frameworks.stdlib.Bufio
9+
import semmle.go.frameworks.stdlib.Bytes
810

911
/** A `String()` method. */
1012
class StringMethod extends TaintTracking::FunctionModel, Method {
@@ -73,17 +75,6 @@ module PathFilePath {
7375
}
7476
}
7577

76-
/** Provides models of commonly used functions in the `bytes` package. */
77-
private module Bytes {
78-
private class BufferBytes extends TaintTracking::FunctionModel, Method {
79-
BufferBytes() { this.hasQualifiedName("bytes", "Buffer", ["Bytes", "String"]) }
80-
81-
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
82-
input.isReceiver() and output.isResult()
83-
}
84-
}
85-
}
86-
8778
/** Provides models of commonly used functions in the `fmt` package. */
8879
module Fmt {
8980
/** The `Sprint` function or one of its variants. */
@@ -384,17 +375,6 @@ module Io {
384375
}
385376
}
386377

387-
/** Provides models of commonly used functions in the `bufio` package. */
388-
module Bufio {
389-
private class NewWriter extends TaintTracking::FunctionModel {
390-
NewWriter() { this.hasQualifiedName("bufio", "NewWriter") }
391-
392-
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
393-
input.isResult() and output.isParameter(0)
394-
}
395-
}
396-
}
397-
398378
/** Provides models of commonly used functions in the `io/ioutil` package. */
399379
module IoUtil {
400380
private class IoUtilFileSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode {
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the `bufio` package.
3+
*/
4+
5+
import go
6+
7+
/** Provides models of commonly used functions in the `bufio` package. */
8+
module Bufio {
9+
private class FunctionModels extends TaintTracking::FunctionModel {
10+
FunctionInput inp;
11+
FunctionOutput outp;
12+
13+
FunctionModels() {
14+
// signature: func NewReadWriter(r *Reader, w *Writer) *ReadWriter
15+
hasQualifiedName("bufio", "NewReadWriter") and
16+
(
17+
inp.isParameter(0) and outp.isResult()
18+
or
19+
inp.isResult() and outp.isParameter(1)
20+
)
21+
or
22+
// signature: func NewReader(rd io.Reader) *Reader
23+
hasQualifiedName("bufio", "NewReader") and
24+
(inp.isParameter(0) and outp.isResult())
25+
or
26+
// signature: func NewReaderSize(rd io.Reader, size int) *Reader
27+
hasQualifiedName("bufio", "NewReaderSize") and
28+
(inp.isParameter(0) and outp.isResult())
29+
or
30+
// signature: func NewScanner(r io.Reader) *Scanner
31+
hasQualifiedName("bufio", "NewScanner") and
32+
(inp.isParameter(0) and outp.isResult())
33+
or
34+
// signature: func NewWriter(w io.Writer) *Writer
35+
hasQualifiedName("bufio", "NewWriter") and
36+
(inp.isResult() and outp.isParameter(0))
37+
or
38+
// signature: func NewWriterSize(w io.Writer, size int) *Writer
39+
hasQualifiedName("bufio", "NewWriterSize") and
40+
(inp.isResult() and outp.isParameter(0))
41+
or
42+
// signature: func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error)
43+
hasQualifiedName("bufio", "ScanBytes") and
44+
(inp.isParameter(0) and outp.isResult(1))
45+
or
46+
// signature: func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error)
47+
hasQualifiedName("bufio", "ScanLines") and
48+
(inp.isParameter(0) and outp.isResult(1))
49+
or
50+
// signature: func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error)
51+
hasQualifiedName("bufio", "ScanRunes") and
52+
(inp.isParameter(0) and outp.isResult(1))
53+
or
54+
// signature: func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error)
55+
hasQualifiedName("bufio", "ScanWords") and
56+
(inp.isParameter(0) and outp.isResult(1))
57+
}
58+
59+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
60+
input = inp and output = outp
61+
}
62+
}
63+
64+
private class MethodModels extends TaintTracking::FunctionModel, Method {
65+
FunctionInput inp;
66+
FunctionOutput outp;
67+
68+
MethodModels() {
69+
// signature: func (*Reader).Peek(n int) ([]byte, error)
70+
this.hasQualifiedName("bufio", "Reader", "Peek") and
71+
(inp.isReceiver() and outp.isResult(0))
72+
or
73+
// signature: func (*Reader).ReadBytes(delim byte) ([]byte, error)
74+
this.hasQualifiedName("bufio", "Reader", "ReadBytes") and
75+
(inp.isReceiver() and outp.isResult(0))
76+
or
77+
// signature: func (*Reader).ReadLine() (line []byte, isPrefix bool, err error)
78+
this.hasQualifiedName("bufio", "Reader", "ReadLine") and
79+
(inp.isReceiver() and outp.isResult(0))
80+
or
81+
// signature: func (*Reader).ReadSlice(delim byte) (line []byte, err error)
82+
this.hasQualifiedName("bufio", "Reader", "ReadSlice") and
83+
(inp.isReceiver() and outp.isResult(0))
84+
or
85+
// signature: func (*Reader).ReadString(delim byte) (string, error)
86+
this.hasQualifiedName("bufio", "Reader", "ReadString") and
87+
(inp.isReceiver() and outp.isResult(0))
88+
or
89+
// signature: func (*Reader).Reset(r io.Reader)
90+
this.hasQualifiedName("bufio", "Reader", "Reset") and
91+
(inp.isParameter(0) and outp.isReceiver())
92+
or
93+
// signature: func (*Reader).WriteTo(w io.Writer) (n int64, err error)
94+
this.hasQualifiedName("bufio", "Reader", "WriteTo") and
95+
(inp.isReceiver() and outp.isParameter(0))
96+
or
97+
// signature: func (*Scanner).Bytes() []byte
98+
this.hasQualifiedName("bufio", "Scanner", "Bytes") and
99+
(inp.isReceiver() and outp.isResult())
100+
or
101+
// signature: func (*Scanner).Text() string
102+
this.hasQualifiedName("bufio", "Scanner", "Text") and
103+
(inp.isReceiver() and outp.isResult())
104+
or
105+
// signature: func (*Writer).ReadFrom(r io.Reader) (n int64, err error)
106+
this.hasQualifiedName("bufio", "Writer", "ReadFrom") and
107+
(inp.isParameter(0) and outp.isReceiver())
108+
or
109+
// signature: func (*Writer).Reset(w io.Writer)
110+
this.hasQualifiedName("bufio", "Writer", "Reset") and
111+
(inp.isReceiver() and outp.isParameter(0))
112+
or
113+
// signature: func (*Writer).Write(p []byte) (nn int, err error)
114+
this.hasQualifiedName("bufio", "Writer", "Write") and
115+
(inp.isParameter(0) and outp.isReceiver())
116+
or
117+
// signature: func (*Writer).WriteString(s string) (int, error)
118+
this.hasQualifiedName("bufio", "Writer", "WriteString") and
119+
(inp.isParameter(0) and outp.isReceiver())
120+
}
121+
122+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
123+
input = inp and output = outp
124+
}
125+
}
126+
}
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the `bytes` package.
3+
*/
4+
5+
import go
6+
7+
/** Provides models of commonly used functions in the `bytes` package. */
8+
module Bytes {
9+
private class FunctionModels extends TaintTracking::FunctionModel {
10+
FunctionInput inp;
11+
FunctionOutput outp;
12+
13+
FunctionModels() {
14+
// signature: func Fields(s []byte) [][]byte
15+
hasQualifiedName("bytes", "Fields") and
16+
(inp.isParameter(0) and outp.isResult())
17+
or
18+
// signature: func FieldsFunc(s []byte, f func(rune) bool) [][]byte
19+
hasQualifiedName("bytes", "FieldsFunc") and
20+
(inp.isParameter(0) and outp.isResult())
21+
or
22+
// signature: func Join(s [][]byte, sep []byte) []byte
23+
hasQualifiedName("bytes", "Join") and
24+
(inp.isParameter(_) and outp.isResult())
25+
or
26+
// signature: func Map(mapping func(r rune) rune, s []byte) []byte
27+
hasQualifiedName("bytes", "Map") and
28+
(inp.isParameter(1) and outp.isResult())
29+
or
30+
// signature: func NewBuffer(buf []byte) *Buffer
31+
hasQualifiedName("bytes", "NewBuffer") and
32+
(inp.isParameter(0) and outp.isResult())
33+
or
34+
// signature: func NewBufferString(s string) *Buffer
35+
hasQualifiedName("bytes", "NewBufferString") and
36+
(inp.isParameter(0) and outp.isResult())
37+
or
38+
// signature: func NewReader(b []byte) *Reader
39+
hasQualifiedName("bytes", "NewReader") and
40+
(inp.isParameter(0) and outp.isResult())
41+
or
42+
// signature: func Repeat(b []byte, count int) []byte
43+
hasQualifiedName("bytes", "Repeat") and
44+
(inp.isParameter(0) and outp.isResult())
45+
or
46+
// signature: func Replace(s []byte, old []byte, new []byte, n int) []byte
47+
hasQualifiedName("bytes", "Replace") and
48+
(inp.isParameter([0, 2]) and outp.isResult())
49+
or
50+
// signature: func ReplaceAll(s []byte, old []byte, new []byte) []byte
51+
hasQualifiedName("bytes", "ReplaceAll") and
52+
(inp.isParameter([0, 2]) and outp.isResult())
53+
or
54+
// signature: func Runes(s []byte) []rune
55+
hasQualifiedName("bytes", "Runes") and
56+
(inp.isParameter(0) and outp.isResult())
57+
or
58+
// signature: func Split(s []byte, sep []byte) [][]byte
59+
hasQualifiedName("bytes", "Split") and
60+
(inp.isParameter(0) and outp.isResult())
61+
or
62+
// signature: func SplitAfter(s []byte, sep []byte) [][]byte
63+
hasQualifiedName("bytes", "SplitAfter") and
64+
(inp.isParameter(0) and outp.isResult())
65+
or
66+
// signature: func SplitAfterN(s []byte, sep []byte, n int) [][]byte
67+
hasQualifiedName("bytes", "SplitAfterN") and
68+
(inp.isParameter(0) and outp.isResult())
69+
or
70+
// signature: func SplitN(s []byte, sep []byte, n int) [][]byte
71+
hasQualifiedName("bytes", "SplitN") and
72+
(inp.isParameter(0) and outp.isResult())
73+
or
74+
// signature: func Title(s []byte) []byte
75+
hasQualifiedName("bytes", "Title") and
76+
(inp.isParameter(0) and outp.isResult())
77+
or
78+
// signature: func ToLower(s []byte) []byte
79+
hasQualifiedName("bytes", "ToLower") and
80+
(inp.isParameter(0) and outp.isResult())
81+
or
82+
// signature: func ToLowerSpecial(c unicode.SpecialCase, s []byte) []byte
83+
hasQualifiedName("bytes", "ToLowerSpecial") and
84+
(inp.isParameter(1) and outp.isResult())
85+
or
86+
// signature: func ToTitle(s []byte) []byte
87+
hasQualifiedName("bytes", "ToTitle") and
88+
(inp.isParameter(0) and outp.isResult())
89+
or
90+
// signature: func ToTitleSpecial(c unicode.SpecialCase, s []byte) []byte
91+
hasQualifiedName("bytes", "ToTitleSpecial") and
92+
(inp.isParameter(1) and outp.isResult())
93+
or
94+
// signature: func ToUpper(s []byte) []byte
95+
hasQualifiedName("bytes", "ToUpper") and
96+
(inp.isParameter(0) and outp.isResult())
97+
or
98+
// signature: func ToUpperSpecial(c unicode.SpecialCase, s []byte) []byte
99+
hasQualifiedName("bytes", "ToUpperSpecial") and
100+
(inp.isParameter(1) and outp.isResult())
101+
or
102+
// signature: func ToValidUTF8(s []byte, replacement []byte) []byte
103+
hasQualifiedName("bytes", "ToValidUTF8") and
104+
(inp.isParameter(_) and outp.isResult())
105+
or
106+
// signature: func Trim(s []byte, cutset string) []byte
107+
hasQualifiedName("bytes", "Trim") and
108+
(inp.isParameter(0) and outp.isResult())
109+
or
110+
// signature: func TrimFunc(s []byte, f func(r rune) bool) []byte
111+
hasQualifiedName("bytes", "TrimFunc") and
112+
(inp.isParameter(0) and outp.isResult())
113+
or
114+
// signature: func TrimLeft(s []byte, cutset string) []byte
115+
hasQualifiedName("bytes", "TrimLeft") and
116+
(inp.isParameter(0) and outp.isResult())
117+
or
118+
// signature: func TrimLeftFunc(s []byte, f func(r rune) bool) []byte
119+
hasQualifiedName("bytes", "TrimLeftFunc") and
120+
(inp.isParameter(0) and outp.isResult())
121+
or
122+
// signature: func TrimPrefix(s []byte, prefix []byte) []byte
123+
hasQualifiedName("bytes", "TrimPrefix") and
124+
(inp.isParameter(0) and outp.isResult())
125+
or
126+
// signature: func TrimRight(s []byte, cutset string) []byte
127+
hasQualifiedName("bytes", "TrimRight") and
128+
(inp.isParameter(0) and outp.isResult())
129+
or
130+
// signature: func TrimRightFunc(s []byte, f func(r rune) bool) []byte
131+
hasQualifiedName("bytes", "TrimRightFunc") and
132+
(inp.isParameter(0) and outp.isResult())
133+
or
134+
// signature: func TrimSpace(s []byte) []byte
135+
hasQualifiedName("bytes", "TrimSpace") and
136+
(inp.isParameter(0) and outp.isResult())
137+
or
138+
// signature: func TrimSuffix(s []byte, suffix []byte) []byte
139+
hasQualifiedName("bytes", "TrimSuffix") and
140+
(inp.isParameter(0) and outp.isResult())
141+
}
142+
143+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
144+
input = inp and output = outp
145+
}
146+
}
147+
148+
private class MethodModels extends TaintTracking::FunctionModel, Method {
149+
FunctionInput inp;
150+
FunctionOutput outp;
151+
152+
MethodModels() {
153+
// signature: func (*Buffer).Bytes() []byte
154+
this.hasQualifiedName("bytes", "Buffer", "Bytes") and
155+
(inp.isReceiver() and outp.isResult())
156+
or
157+
// signature: func (*Buffer).Next(n int) []byte
158+
this.hasQualifiedName("bytes", "Buffer", "Next") and
159+
(inp.isReceiver() and outp.isResult())
160+
or
161+
// signature: func (*Buffer).ReadBytes(delim byte) (line []byte, err error)
162+
this.hasQualifiedName("bytes", "Buffer", "ReadBytes") and
163+
(inp.isReceiver() and outp.isResult(0))
164+
or
165+
// signature: func (*Buffer).ReadFrom(r io.Reader) (n int64, err error)
166+
this.hasQualifiedName("bytes", "Buffer", "ReadFrom") and
167+
(inp.isParameter(0) and outp.isReceiver())
168+
or
169+
// signature: func (*Buffer).ReadString(delim byte) (line string, err error)
170+
this.hasQualifiedName("bytes", "Buffer", "ReadString") and
171+
(inp.isReceiver() and outp.isResult(0))
172+
or
173+
// signature: func (*Buffer).String() string
174+
this.hasQualifiedName("bytes", "Buffer", "String") and
175+
(inp.isReceiver() and outp.isResult())
176+
or
177+
// signature: func (*Buffer).Write(p []byte) (n int, err error)
178+
this.hasQualifiedName("bytes", "Buffer", "Write") and
179+
(inp.isParameter(0) and outp.isReceiver())
180+
or
181+
// signature: func (*Buffer).WriteString(s string) (n int, err error)
182+
this.hasQualifiedName("bytes", "Buffer", "WriteString") and
183+
(inp.isParameter(0) and outp.isReceiver())
184+
or
185+
// signature: func (*Buffer).WriteTo(w io.Writer) (n int64, err error)
186+
this.hasQualifiedName("bytes", "Buffer", "WriteTo") and
187+
(inp.isReceiver() and outp.isParameter(0))
188+
or
189+
// signature: func (*Reader).ReadAt(b []byte, off int64) (n int, err error)
190+
this.hasQualifiedName("bytes", "Reader", "ReadAt") and
191+
(inp.isReceiver() and outp.isParameter(0))
192+
or
193+
// signature: func (*Reader).Reset(b []byte)
194+
this.hasQualifiedName("bytes", "Reader", "Reset") and
195+
(inp.isParameter(0) and outp.isReceiver())
196+
or
197+
// signature: func (*Reader).WriteTo(w io.Writer) (n int64, err error)
198+
this.hasQualifiedName("bytes", "Reader", "WriteTo") and
199+
(inp.isReceiver() and outp.isParameter(0))
200+
}
201+
202+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
203+
input = inp and output = outp
204+
}
205+
}
206+
}

0 commit comments

Comments
 (0)