Skip to content

Commit e13c4b7

Browse files
committed
Treat container flow as taint flow in localTaintStep
1 parent 066db76 commit e13c4b7

File tree

4 files changed

+62
-2
lines changed

4 files changed

+62
-2
lines changed

go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll

+10
Original file line numberDiff line numberDiff line change
@@ -458,3 +458,13 @@ class ContentApprox = Unit;
458458
/** Gets an approximated value for content `c`. */
459459
pragma[inline]
460460
ContentApprox getContentApprox(Content c) { any() }
461+
462+
/**
463+
* Holds if the the content `c` is a container.
464+
*/
465+
predicate containerContent(ContentSet c) {
466+
c instanceof ArrayContent or
467+
c instanceof CollectionContent or
468+
c instanceof MapKeyContent or
469+
c instanceof MapValueContent
470+
}

go/ql/lib/semmle/go/dataflow/internal/TaintTrackingUtil.qll

+12-2
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,21 @@ predicate localExprTaint(Expr src, Expr sink) {
2727
* Holds if taint can flow in one local step from `src` to `sink`.
2828
*/
2929
predicate localTaintStep(DataFlow::Node src, DataFlow::Node sink) {
30-
DataFlow::localFlowStep(src, sink) or
31-
localAdditionalTaintStep(src, sink, _) or
30+
DataFlow::localFlowStep(src, sink)
31+
or
32+
localAdditionalTaintStep(src, sink, _)
33+
or
3234
// Simple flow through library code is included in the exposed local
3335
// step relation, even though flow is technically inter-procedural
3436
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(src, sink, _)
37+
or
38+
// Treat container flow as taint for the local taint flow relation
39+
exists(DataFlow::Content c | DataFlowPrivate::containerContent(c) |
40+
DataFlowPrivate::readStep(src, c, sink) or
41+
DataFlowPrivate::storeStep(src, c, sink) or
42+
FlowSummaryImpl::Private::Steps::summaryGetterStep(src, c, sink, _) or
43+
FlowSummaryImpl::Private::Steps::summarySetterStep(src, c, sink, _)
44+
)
3545
}
3646

3747
private Type getElementType(Type containerType) {

go/ql/test/library-tests/semmle/go/dataflow/FlowSteps/LocalTaintStep.expected

+28
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,36 @@
55
| main.go:38:19:38:19 | 3 | main.go:38:7:38:20 | slice literal |
66
| main.go:39:8:39:25 | []type{args} | main.go:39:8:39:25 | call to append |
77
| main.go:39:15:39:15 | s | main.go:39:8:39:25 | call to append |
8+
| main.go:39:18:39:18 | 4 | main.go:39:8:39:25 | []type{args} |
9+
| main.go:39:21:39:21 | 5 | main.go:39:8:39:25 | []type{args} |
10+
| main.go:39:24:39:24 | 6 | main.go:39:8:39:25 | []type{args} |
811
| main.go:40:15:40:15 | s | main.go:40:8:40:23 | call to append |
912
| main.go:40:18:40:19 | s1 | main.go:40:8:40:23 | call to append |
1013
| main.go:42:10:42:11 | s4 | main.go:38:2:38:2 | definition of s |
1114
| main.go:47:20:47:21 | next key-value pair in range | main.go:47:2:50:2 | range statement[0] |
1215
| main.go:47:20:47:21 | next key-value pair in range | main.go:47:2:50:2 | range statement[1] |
1316
| main.go:47:20:47:21 | xs | main.go:47:2:50:2 | range statement[1] |
17+
| main.go:56:8:56:11 | true | main.go:56:2:56:3 | ch |
18+
| main.go:57:4:57:5 | ch | main.go:57:2:57:5 | <-... |
1419
| strings.go:9:24:9:24 | s | strings.go:9:8:9:38 | call to Replace |
1520
| strings.go:9:32:9:34 | "_" | strings.go:9:8:9:38 | call to Replace |
1621
| strings.go:10:27:10:27 | s | strings.go:10:8:10:42 | call to ReplaceAll |
1722
| strings.go:10:35:10:41 | "&amp;" | strings.go:10:8:10:42 | call to ReplaceAll |
23+
| strings.go:11:9:11:26 | []type{args} | strings.go:11:9:11:26 | call to Sprint |
1824
| strings.go:11:9:11:26 | call to Sprint | strings.go:11:9:11:50 | ...+... |
1925
| strings.go:11:9:11:50 | ...+... | strings.go:11:9:11:69 | ...+... |
26+
| strings.go:11:20:11:21 | s2 | strings.go:11:9:11:26 | []type{args} |
2027
| strings.go:11:20:11:21 | s2 | strings.go:11:9:11:26 | call to Sprint |
28+
| strings.go:11:24:11:25 | s3 | strings.go:11:9:11:26 | []type{args} |
2129
| strings.go:11:24:11:25 | s3 | strings.go:11:9:11:26 | call to Sprint |
30+
| strings.go:11:30:11:50 | []type{args} | strings.go:11:30:11:50 | call to Sprintf |
2231
| strings.go:11:30:11:50 | call to Sprintf | strings.go:11:9:11:50 | ...+... |
2332
| strings.go:11:42:11:45 | "%q" | strings.go:11:30:11:50 | call to Sprintf |
33+
| strings.go:11:48:11:49 | s2 | strings.go:11:30:11:50 | []type{args} |
2434
| strings.go:11:48:11:49 | s2 | strings.go:11:30:11:50 | call to Sprintf |
35+
| strings.go:11:54:11:69 | []type{args} | strings.go:11:54:11:69 | call to Sprintln |
2536
| strings.go:11:54:11:69 | call to Sprintln | strings.go:11:9:11:69 | ...+... |
37+
| strings.go:11:67:11:68 | s3 | strings.go:11:54:11:69 | []type{args} |
2638
| strings.go:11:67:11:68 | s3 | strings.go:11:54:11:69 | call to Sprintln |
2739
| url.go:12:14:12:48 | call to PathUnescape | url.go:12:3:12:48 | ... = ...[0] |
2840
| url.go:12:14:12:48 | call to PathUnescape | url.go:12:3:12:48 | ... = ...[1] |
@@ -39,17 +51,25 @@
3951
| url.go:27:9:27:30 | call to ParseRequestURI | url.go:27:2:27:30 | ... = ...[1] |
4052
| url.go:27:29:27:29 | s | url.go:27:2:27:30 | ... = ...[0] |
4153
| url.go:28:14:28:14 | u | url.go:28:14:28:28 | call to EscapedPath |
54+
| url.go:28:14:28:28 | call to EscapedPath | url.go:28:2:28:29 | []type{args} |
4255
| url.go:29:14:29:14 | u | url.go:29:14:29:25 | call to Hostname |
56+
| url.go:29:14:29:25 | call to Hostname | url.go:29:2:29:26 | []type{args} |
4357
| url.go:30:11:30:11 | u | url.go:30:2:30:27 | ... := ...[0] |
4458
| url.go:30:11:30:27 | call to MarshalBinary | url.go:30:2:30:27 | ... := ...[0] |
4559
| url.go:30:11:30:27 | call to MarshalBinary | url.go:30:2:30:27 | ... := ...[1] |
60+
| url.go:31:2:31:16 | []type{args} | url.go:30:2:30:3 | definition of bs |
61+
| url.go:31:14:31:15 | bs | url.go:31:2:31:16 | []type{args} |
4662
| url.go:32:9:32:9 | u | url.go:32:2:32:23 | ... = ...[0] |
4763
| url.go:32:9:32:23 | call to Parse | url.go:32:2:32:23 | ... = ...[0] |
4864
| url.go:32:9:32:23 | call to Parse | url.go:32:2:32:23 | ... = ...[1] |
4965
| url.go:32:17:32:22 | "/foo" | url.go:32:2:32:23 | ... = ...[0] |
5066
| url.go:33:14:33:14 | u | url.go:33:14:33:21 | call to Port |
67+
| url.go:33:14:33:21 | call to Port | url.go:33:2:33:22 | []type{args} |
68+
| url.go:34:2:34:23 | []type{args} | url.go:34:14:34:22 | call to Query |
5169
| url.go:34:14:34:14 | u | url.go:34:14:34:22 | call to Query |
70+
| url.go:34:14:34:22 | call to Query | url.go:34:2:34:23 | []type{args} |
5271
| url.go:35:14:35:14 | u | url.go:35:14:35:27 | call to RequestURI |
72+
| url.go:35:14:35:27 | call to RequestURI | url.go:35:2:35:28 | []type{args} |
5373
| url.go:36:6:36:6 | u | url.go:36:6:36:26 | call to ResolveReference |
5474
| url.go:36:25:36:25 | u | url.go:36:6:36:26 | call to ResolveReference |
5575
| url.go:41:17:41:20 | "me" | url.go:41:8:41:21 | call to User |
@@ -58,27 +78,35 @@
5878
| url.go:43:11:43:12 | ui | url.go:43:2:43:23 | ... := ...[0] |
5979
| url.go:43:11:43:23 | call to Password | url.go:43:2:43:23 | ... := ...[0] |
6080
| url.go:43:11:43:23 | call to Password | url.go:43:2:43:23 | ... := ...[1] |
81+
| url.go:44:14:44:15 | pw | url.go:44:2:44:16 | []type{args} |
6182
| url.go:45:14:45:15 | ui | url.go:45:14:45:26 | call to Username |
83+
| url.go:45:14:45:26 | call to Username | url.go:45:2:45:27 | []type{args} |
6284
| url.go:50:10:50:26 | call to ParseQuery | url.go:50:2:50:26 | ... := ...[0] |
6385
| url.go:50:10:50:26 | call to ParseQuery | url.go:50:2:50:26 | ... := ...[1] |
6486
| url.go:50:25:50:25 | q | url.go:50:2:50:26 | ... := ...[0] |
6587
| url.go:51:14:51:14 | v | url.go:51:14:51:23 | call to Encode |
88+
| url.go:51:14:51:23 | call to Encode | url.go:51:2:51:24 | []type{args} |
6689
| url.go:52:14:52:14 | v | url.go:52:14:52:26 | call to Get |
90+
| url.go:52:14:52:26 | call to Get | url.go:52:2:52:27 | []type{args} |
6791
| url.go:57:16:57:39 | call to JoinPath | url.go:57:2:57:39 | ... := ...[0] |
6892
| url.go:57:16:57:39 | call to JoinPath | url.go:57:2:57:39 | ... := ...[1] |
6993
| url.go:57:29:57:29 | q | url.go:57:2:57:39 | ... := ...[0] |
7094
| url.go:57:32:57:38 | "clean" | url.go:57:2:57:39 | ... := ...[0] |
95+
| url.go:57:32:57:38 | "clean" | url.go:57:16:57:39 | []type{args} |
7196
| url.go:58:16:58:45 | call to JoinPath | url.go:58:2:58:45 | ... := ...[0] |
7297
| url.go:58:16:58:45 | call to JoinPath | url.go:58:2:58:45 | ... := ...[1] |
7398
| url.go:58:29:58:35 | "clean" | url.go:58:2:58:45 | ... := ...[0] |
7499
| url.go:58:38:58:44 | joined1 | url.go:58:2:58:45 | ... := ...[0] |
100+
| url.go:58:38:58:44 | joined1 | url.go:58:16:58:45 | []type{args} |
75101
| url.go:59:14:59:31 | call to Parse | url.go:59:2:59:31 | ... := ...[0] |
76102
| url.go:59:14:59:31 | call to Parse | url.go:59:2:59:31 | ... := ...[1] |
77103
| url.go:59:24:59:30 | joined2 | url.go:59:2:59:31 | ... := ...[0] |
78104
| url.go:60:15:60:19 | asUrl | url.go:60:15:60:37 | call to JoinPath |
105+
| url.go:60:30:60:36 | "clean" | url.go:60:15:60:37 | []type{args} |
79106
| url.go:60:30:60:36 | "clean" | url.go:60:15:60:37 | call to JoinPath |
80107
| url.go:65:17:65:48 | call to Parse | url.go:65:2:65:48 | ... := ...[0] |
81108
| url.go:65:17:65:48 | call to Parse | url.go:65:2:65:48 | ... := ...[1] |
82109
| url.go:65:27:65:47 | "http://harmless.org" | url.go:65:2:65:48 | ... := ...[0] |
83110
| url.go:66:9:66:16 | cleanUrl | url.go:66:9:66:28 | call to JoinPath |
111+
| url.go:66:27:66:27 | q | url.go:66:9:66:28 | []type{args} |
84112
| url.go:66:27:66:27 | q | url.go:66:9:66:28 | call to JoinPath |

go/ql/test/library-tests/semmle/go/frameworks/TaintSteps/TaintStep.expected

+12
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ invalidModelRow
1010
| io.go:14:31:14:43 | "some string" | io.go:14:13:14:44 | call to NewReader |
1111
| io.go:16:3:16:3 | definition of w | io.go:16:23:16:27 | &... |
1212
| io.go:16:3:16:3 | definition of w | io.go:16:30:16:34 | &... |
13+
| io.go:16:8:16:35 | []type{args} | io.go:16:23:16:27 | &... |
14+
| io.go:16:8:16:35 | []type{args} | io.go:16:30:16:34 | &... |
1315
| io.go:16:23:16:27 | &... | io.go:15:7:15:10 | definition of buf1 |
16+
| io.go:16:23:16:27 | &... | io.go:16:8:16:35 | []type{args} |
1417
| io.go:16:24:16:27 | buf1 | io.go:16:23:16:27 | &... |
1518
| io.go:16:30:16:34 | &... | io.go:15:13:15:16 | definition of buf2 |
19+
| io.go:16:30:16:34 | &... | io.go:16:8:16:35 | []type{args} |
1620
| io.go:16:31:16:34 | buf2 | io.go:16:30:16:34 | &... |
1721
| io.go:18:14:18:19 | reader | io.go:16:3:16:3 | definition of w |
1822
| io.go:22:31:22:43 | "some string" | io.go:22:13:22:44 | call to NewReader |
@@ -27,8 +31,10 @@ invalidModelRow
2731
| io.go:39:11:39:19 | call to Pipe | io.go:39:3:39:19 | ... := ...[0] |
2832
| io.go:39:11:39:19 | call to Pipe | io.go:39:3:39:19 | ... := ...[1] |
2933
| io.go:40:17:40:31 | "some string\\n" | io.go:39:6:39:6 | definition of w |
34+
| io.go:40:17:40:31 | "some string\\n" | io.go:40:3:40:32 | []type{args} |
3035
| io.go:43:16:43:16 | r | io.go:42:3:42:5 | definition of buf |
3136
| io.go:44:13:44:15 | buf | io.go:44:13:44:24 | call to String |
37+
| io.go:44:13:44:24 | call to String | io.go:44:3:44:25 | []type{args} |
3238
| io.go:48:31:48:43 | "some string" | io.go:48:13:48:44 | call to NewReader |
3339
| io.go:50:18:50:23 | reader | io.go:49:3:49:5 | definition of buf |
3440
| io.go:54:31:54:43 | "some string" | io.go:54:13:54:44 | call to NewReader |
@@ -46,8 +52,14 @@ invalidModelRow
4652
| io.go:82:27:82:36 | "reader1 " | io.go:82:9:82:37 | call to NewReader |
4753
| io.go:83:27:83:36 | "reader2 " | io.go:83:9:83:37 | call to NewReader |
4854
| io.go:84:27:84:35 | "reader3" | io.go:84:9:84:36 | call to NewReader |
55+
| io.go:85:8:85:33 | []type{args} | io.go:82:3:82:4 | definition of r1 |
56+
| io.go:85:8:85:33 | []type{args} | io.go:83:3:83:4 | definition of r2 |
57+
| io.go:85:8:85:33 | []type{args} | io.go:84:3:84:4 | definition of r3 |
58+
| io.go:85:23:85:24 | r1 | io.go:85:8:85:33 | []type{args} |
4959
| io.go:85:23:85:24 | r1 | io.go:85:8:85:33 | call to MultiReader |
60+
| io.go:85:27:85:28 | r2 | io.go:85:8:85:33 | []type{args} |
5061
| io.go:85:27:85:28 | r2 | io.go:85:8:85:33 | call to MultiReader |
62+
| io.go:85:31:85:32 | r3 | io.go:85:8:85:33 | []type{args} |
5163
| io.go:85:31:85:32 | r3 | io.go:85:8:85:33 | call to MultiReader |
5264
| io.go:86:22:86:22 | r | io.go:86:11:86:19 | selection of Stdout |
5365
| io.go:89:26:89:38 | "some string" | io.go:89:8:89:39 | call to NewReader |

0 commit comments

Comments
 (0)