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

Commit c10942d

Browse files
authored
Merge pull request #320 from gagliardetto/standard-lib-pt-24
Add taint-tracking for packages inside `text/*`
2 parents 84def5f + c889bc3 commit c10942d

File tree

7 files changed

+407
-42
lines changed

7 files changed

+407
-42
lines changed

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

Lines changed: 3 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ import semmle.go.frameworks.stdlib.CompressZlib
1515
import semmle.go.frameworks.stdlib.Path
1616
import semmle.go.frameworks.stdlib.PathFilepath
1717
import semmle.go.frameworks.stdlib.Reflect
18+
import semmle.go.frameworks.stdlib.TextScanner
19+
import semmle.go.frameworks.stdlib.TextTabwriter
20+
import semmle.go.frameworks.stdlib.TextTemplate
1821

1922
/** A `String()` method. */
2023
class StringMethod extends TaintTracking::FunctionModel, Method {
@@ -576,48 +579,6 @@ module Strings {
576579
}
577580
}
578581

579-
/** Provides models of commonly used functions in the `text/template` package. */
580-
module Template {
581-
private class TemplateEscape extends EscapeFunction::Range {
582-
string kind;
583-
584-
TemplateEscape() {
585-
exists(string fn |
586-
fn.matches("HTMLEscape%") and kind = "html"
587-
or
588-
fn.matches("JSEscape%") and kind = "js"
589-
or
590-
fn.matches("URLQueryEscape%") and kind = "url"
591-
|
592-
this.hasQualifiedName("text/template", fn)
593-
or
594-
this.hasQualifiedName("html/template", fn)
595-
)
596-
}
597-
598-
override string kind() { result = kind }
599-
}
600-
601-
private class TextTemplateInstantiation extends TemplateInstantiation::Range,
602-
DataFlow::MethodCallNode {
603-
int dataArg;
604-
605-
TextTemplateInstantiation() {
606-
exists(string m | getTarget().hasQualifiedName("text/template", "Template", m) |
607-
m = "Execute" and
608-
dataArg = 1
609-
or
610-
m = "ExecuteTemplate" and
611-
dataArg = 2
612-
)
613-
}
614-
615-
override DataFlow::Node getTemplateArgument() { result = this.getReceiver() }
616-
617-
override DataFlow::Node getADataArgument() { result = this.getArgument(dataArg) }
618-
}
619-
}
620-
621582
/** Provides models of commonly used functions in the `net/url` package. */
622583
module URL {
623584
/** The `PathEscape` or `QueryEscape` function. */
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the `text/scanner` package.
3+
*/
4+
5+
import go
6+
7+
/** Provides models of commonly used functions in the `text/scanner` package. */
8+
module TextScanner {
9+
private class MethodModels extends TaintTracking::FunctionModel, Method {
10+
FunctionInput inp;
11+
FunctionOutput outp;
12+
13+
MethodModels() {
14+
// signature: func (*Scanner).Init(src io.Reader) *Scanner
15+
this.hasQualifiedName("text/scanner", "Scanner", "Init") and
16+
(
17+
inp.isParameter(0) and
18+
(outp.isReceiver() or outp.isResult())
19+
)
20+
or
21+
// signature: func (*Scanner).TokenText() string
22+
this.hasQualifiedName("text/scanner", "Scanner", "TokenText") and
23+
(inp.isReceiver() and outp.isResult())
24+
}
25+
26+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
27+
input = inp and output = outp
28+
}
29+
}
30+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the `text/tabwriter` package.
3+
*/
4+
5+
import go
6+
7+
/** Provides models of commonly used functions in the `text/tabwriter` package. */
8+
module TextTabwriter {
9+
private class FunctionModels extends TaintTracking::FunctionModel {
10+
FunctionInput inp;
11+
FunctionOutput outp;
12+
13+
FunctionModels() {
14+
// signature: func NewWriter(output io.Writer, minwidth int, tabwidth int, padding int, padchar byte, flags uint) *Writer
15+
hasQualifiedName("text/tabwriter", "NewWriter") and
16+
(inp.isResult() and outp.isParameter(0))
17+
}
18+
19+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
20+
input = inp and output = outp
21+
}
22+
}
23+
24+
private class MethodModels extends TaintTracking::FunctionModel, Method {
25+
FunctionInput inp;
26+
FunctionOutput outp;
27+
28+
MethodModels() {
29+
// signature: func (*Writer).Init(output io.Writer, minwidth int, tabwidth int, padding int, padchar byte, flags uint) *Writer
30+
this.hasQualifiedName("text/tabwriter", "Writer", "Init") and
31+
(
32+
(inp.isReceiver() or inp.isResult()) and
33+
outp.isParameter(0)
34+
)
35+
or
36+
// signature: func (*Writer).Write(buf []byte) (n int, err error)
37+
this.hasQualifiedName("text/tabwriter", "Writer", "Write") and
38+
(inp.isParameter(0) and outp.isReceiver())
39+
}
40+
41+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
42+
input = inp and output = outp
43+
}
44+
}
45+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/**
2+
* Provides classes modeling security-relevant aspects of the `text/template` package.
3+
*/
4+
5+
import go
6+
7+
/** Provides models of commonly used functions in the `text/template` package. */
8+
module TextTemplate {
9+
private class TemplateEscape extends EscapeFunction::Range {
10+
string kind;
11+
12+
TemplateEscape() {
13+
exists(string fn |
14+
fn.matches("HTMLEscape%") and kind = "html"
15+
or
16+
fn.matches("JSEscape%") and kind = "js"
17+
or
18+
fn.matches("URLQueryEscape%") and kind = "url"
19+
|
20+
this.hasQualifiedName("text/template", fn)
21+
or
22+
this.hasQualifiedName("html/template", fn)
23+
)
24+
}
25+
26+
override string kind() { result = kind }
27+
}
28+
29+
private class TextTemplateInstantiation extends TemplateInstantiation::Range,
30+
DataFlow::MethodCallNode {
31+
int dataArg;
32+
33+
TextTemplateInstantiation() {
34+
exists(string m | getTarget().hasQualifiedName("text/template", "Template", m) |
35+
m = "Execute" and
36+
dataArg = 1
37+
or
38+
m = "ExecuteTemplate" and
39+
dataArg = 2
40+
)
41+
}
42+
43+
override DataFlow::Node getTemplateArgument() { result = this.getReceiver() }
44+
45+
override DataFlow::Node getADataArgument() { result = this.getArgument(dataArg) }
46+
}
47+
48+
private class FunctionModels extends TaintTracking::FunctionModel {
49+
FunctionInput inp;
50+
FunctionOutput outp;
51+
52+
FunctionModels() {
53+
// signature: func HTMLEscape(w io.Writer, b []byte)
54+
hasQualifiedName("text/template", "HTMLEscape") and
55+
(inp.isParameter(1) and outp.isParameter(0))
56+
or
57+
// signature: func HTMLEscapeString(s string) string
58+
hasQualifiedName("text/template", "HTMLEscapeString") and
59+
(inp.isParameter(0) and outp.isResult())
60+
or
61+
// signature: func HTMLEscaper(args ...interface{}) string
62+
hasQualifiedName("text/template", "HTMLEscaper") and
63+
(inp.isParameter(_) and outp.isResult())
64+
or
65+
// signature: func JSEscape(w io.Writer, b []byte)
66+
hasQualifiedName("text/template", "JSEscape") and
67+
(inp.isParameter(1) and outp.isParameter(0))
68+
or
69+
// signature: func JSEscapeString(s string) string
70+
hasQualifiedName("text/template", "JSEscapeString") and
71+
(inp.isParameter(0) and outp.isResult())
72+
or
73+
// signature: func JSEscaper(args ...interface{}) string
74+
hasQualifiedName("text/template", "JSEscaper") and
75+
(inp.isParameter(_) and outp.isResult())
76+
or
77+
// signature: func URLQueryEscaper(args ...interface{}) string
78+
hasQualifiedName("text/template", "URLQueryEscaper") and
79+
(inp.isParameter(_) and outp.isResult())
80+
}
81+
82+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
83+
input = inp and output = outp
84+
}
85+
}
86+
87+
private class MethodModels extends TaintTracking::FunctionModel, Method {
88+
FunctionInput inp;
89+
FunctionOutput outp;
90+
91+
MethodModels() {
92+
// signature: func (*Template).Execute(wr io.Writer, data interface{}) error
93+
this.hasQualifiedName("text/template", "Template", "Execute") and
94+
(inp.isParameter(1) and outp.isParameter(0))
95+
or
96+
// signature: func (*Template).ExecuteTemplate(wr io.Writer, name string, data interface{}) error
97+
this.hasQualifiedName("text/template", "Template", "ExecuteTemplate") and
98+
(inp.isParameter(2) and outp.isParameter(0))
99+
}
100+
101+
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
102+
input = inp and output = outp
103+
}
104+
}
105+
}

ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/TextScanner.go

Lines changed: 46 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/TextTabwriter.go

Lines changed: 62 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)