Skip to content

Commit ac54da7

Browse files
authored
Merge pull request #11002 from owen-mc/dataflow/sync-go-libraries
Update go libraries to 55e052a
2 parents 254a5b0 + 4073d77 commit ac54da7

File tree

49 files changed

+3565
-2062
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+3565
-2062
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: breaking
3+
---
4+
The signature of `allowImplicitRead` on `DataFlow::Configuration` and `TaintTracking::Configuration` has changed from `allowImplicitRead(DataFlow::Node node, DataFlow::Content c)` to `allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c)`.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: deprecated
3+
---
4+
* The `BarrierGuard` class has been deprecated. Such barriers and sanitizers can now instead be created using the new `BarrierGuard` parameterized module.

go/ql/lib/semmle/go/dataflow/ExternalFlow.qll

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,17 @@ predicate sinkModel(string row) { any(SinkModelCsv s).row(row) }
124124
/** Holds if `row` is a summary model. */
125125
predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) }
126126

127+
bindingset[input]
128+
private predicate getKind(string input, string kind, boolean generated) {
129+
input.splitAt(":", 0) = "generated" and kind = input.splitAt(":", 1) and generated = true
130+
or
131+
not input.matches("%:%") and kind = input and generated = false
132+
}
133+
127134
/** Holds if a source model exists for the given parameters. */
128135
predicate sourceModel(
129136
string namespace, string type, boolean subtypes, string name, string signature, string ext,
130-
string output, string kind
137+
string output, string kind, boolean generated
131138
) {
132139
exists(string row |
133140
sourceModel(row) and
@@ -139,14 +146,14 @@ predicate sourceModel(
139146
row.splitAt(";", 4) = signature and
140147
row.splitAt(";", 5) = ext and
141148
row.splitAt(";", 6) = output and
142-
row.splitAt(";", 7) = kind
149+
exists(string k | row.splitAt(";", 7) = k and getKind(k, kind, generated))
143150
)
144151
}
145152

146153
/** Holds if a sink model exists for the given parameters. */
147154
predicate sinkModel(
148155
string namespace, string type, boolean subtypes, string name, string signature, string ext,
149-
string input, string kind
156+
string input, string kind, boolean generated
150157
) {
151158
exists(string row |
152159
sinkModel(row) and
@@ -158,22 +165,22 @@ predicate sinkModel(
158165
row.splitAt(";", 4) = signature and
159166
row.splitAt(";", 5) = ext and
160167
row.splitAt(";", 6) = input and
161-
row.splitAt(";", 7) = kind
168+
exists(string k | row.splitAt(";", 7) = k and getKind(k, kind, generated))
162169
)
163170
}
164171

165172
/** Holds if a summary model exists for the given parameters. */
166173
predicate summaryModel(
167174
string namespace, string type, boolean subtypes, string name, string signature, string ext,
168-
string input, string output, string kind
175+
string input, string output, string kind, boolean generated
169176
) {
170-
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, _)
177+
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, generated, _)
171178
}
172179

173180
/** Holds if a summary model `row` exists for the given parameters. */
174181
predicate summaryModel(
175182
string namespace, string type, boolean subtypes, string name, string signature, string ext,
176-
string input, string output, string kind, string row
183+
string input, string output, string kind, boolean generated, string row
177184
) {
178185
summaryModel(row) and
179186
row.splitAt(";", 0) = namespace and
@@ -185,14 +192,14 @@ predicate summaryModel(
185192
row.splitAt(";", 5) = ext and
186193
row.splitAt(";", 6) = input and
187194
row.splitAt(";", 7) = output and
188-
row.splitAt(";", 8) = kind
195+
exists(string k | row.splitAt(";", 8) = k and getKind(k, kind, generated))
189196
}
190197

191198
/** Holds if `package` have CSV framework coverage. */
192199
private predicate packageHasCsvCoverage(string package) {
193-
sourceModel(package, _, _, _, _, _, _, _) or
194-
sinkModel(package, _, _, _, _, _, _, _) or
195-
summaryModel(package, _, _, _, _, _, _, _, _)
200+
sourceModel(package, _, _, _, _, _, _, _, _) or
201+
sinkModel(package, _, _, _, _, _, _, _, _) or
202+
summaryModel(package, _, _, _, _, _, _, _, _, _)
196203
}
197204

198205
/**
@@ -234,25 +241,25 @@ predicate modelCoverage(string package, int pkgs, string kind, string part, int
234241
part = "source" and
235242
n =
236243
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
237-
string ext, string output |
244+
string ext, string output, boolean generated |
238245
canonicalPackageHasASubpackage(package, subpkg) and
239-
sourceModel(subpkg, type, subtypes, name, signature, ext, output, kind)
246+
sourceModel(subpkg, type, subtypes, name, signature, ext, output, kind, generated)
240247
)
241248
or
242249
part = "sink" and
243250
n =
244251
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
245-
string ext, string input |
252+
string ext, string input, boolean generated |
246253
canonicalPackageHasASubpackage(package, subpkg) and
247-
sinkModel(subpkg, type, subtypes, name, signature, ext, input, kind)
254+
sinkModel(subpkg, type, subtypes, name, signature, ext, input, kind, generated)
248255
)
249256
or
250257
part = "summary" and
251258
n =
252259
strictcount(string subpkg, string type, boolean subtypes, string name, string signature,
253-
string ext, string input, string output |
260+
string ext, string input, string output, boolean generated |
254261
canonicalPackageHasASubpackage(package, subpkg) and
255-
summaryModel(subpkg, type, subtypes, name, signature, ext, input, output, kind)
262+
summaryModel(subpkg, type, subtypes, name, signature, ext, input, output, kind, generated)
256263
)
257264
)
258265
}
@@ -261,9 +268,9 @@ predicate modelCoverage(string package, int pkgs, string kind, string part, int
261268
module CsvValidation {
262269
private string getInvalidModelInput() {
263270
exists(string pred, AccessPath input, string part |
264-
sinkModel(_, _, _, _, _, _, input, _) and pred = "sink"
271+
sinkModel(_, _, _, _, _, _, input, _, _) and pred = "sink"
265272
or
266-
summaryModel(_, _, _, _, _, _, input, _, _) and pred = "summary"
273+
summaryModel(_, _, _, _, _, _, input, _, _, _) and pred = "summary"
267274
|
268275
(
269276
invalidSpecComponent(input, part) and
@@ -279,9 +286,9 @@ module CsvValidation {
279286

280287
private string getInvalidModelOutput() {
281288
exists(string pred, string output, string part |
282-
sourceModel(_, _, _, _, _, _, output, _) and pred = "source"
289+
sourceModel(_, _, _, _, _, _, output, _, _) and pred = "source"
283290
or
284-
summaryModel(_, _, _, _, _, _, _, output, _) and pred = "summary"
291+
summaryModel(_, _, _, _, _, _, _, output, _, _) and pred = "summary"
285292
|
286293
invalidSpecComponent(output, part) and
287294
not part = "" and
@@ -291,8 +298,9 @@ module CsvValidation {
291298
}
292299

293300
private string getInvalidModelKind() {
294-
exists(string row, string kind | summaryModel(row) |
295-
kind = row.splitAt(";", 8) and
301+
exists(string row, string k, string kind | summaryModel(row) |
302+
k = row.splitAt(";", 8) and
303+
getKind(k, kind, _) and
296304
not kind = ["taint", "value"] and
297305
result = "Invalid kind \"" + kind + "\" in summary model."
298306
)
@@ -334,11 +342,11 @@ module CsvValidation {
334342

335343
private string getInvalidModelSignature() {
336344
exists(string pred, string namespace, string type, string name, string signature, string ext |
337-
sourceModel(namespace, type, _, name, signature, ext, _, _) and pred = "source"
345+
sourceModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "source"
338346
or
339-
sinkModel(namespace, type, _, name, signature, ext, _, _) and pred = "sink"
347+
sinkModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "sink"
340348
or
341-
summaryModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "summary"
349+
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "summary"
342350
|
343351
not namespace.regexpMatch("[a-zA-Z0-9_\\./]*") and
344352
result = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
@@ -371,9 +379,9 @@ pragma[nomagic]
371379
private predicate elementSpec(
372380
string namespace, string type, boolean subtypes, string name, string signature, string ext
373381
) {
374-
sourceModel(namespace, type, subtypes, name, signature, ext, _, _) or
375-
sinkModel(namespace, type, subtypes, name, signature, ext, _, _) or
376-
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _)
382+
sourceModel(namespace, type, subtypes, name, signature, ext, _, _, _) or
383+
sinkModel(namespace, type, subtypes, name, signature, ext, _, _, _) or
384+
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _)
377385
}
378386

379387
private string paramsStringPart(Function f, int i) {
@@ -421,7 +429,9 @@ SourceOrSinkElement interpretElement(
421429
predicate hasExternalSpecification(Function f) {
422430
f = any(SummarizedCallable sc).asFunction()
423431
or
424-
exists(SourceOrSinkElement e | f = e.asEntity() | sourceElement(e, _, _) or sinkElement(e, _, _))
432+
exists(SourceOrSinkElement e | f = e.asEntity() |
433+
sourceElement(e, _, _, _) or sinkElement(e, _, _, _)
434+
)
425435
}
426436

427437
private predicate parseField(AccessPathToken c, DataFlow::FieldContent f) {

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

Lines changed: 104 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,109 @@
66
* (which does not use the shared data flow libraries).
77
*/
88

9+
/**
10+
* Convenience-predicate for extracting two capture groups at once.
11+
*/
12+
bindingset[input, regexp]
13+
private predicate regexpCaptureTwo(string input, string regexp, string capture1, string capture2) {
14+
capture1 = input.regexpCapture(regexp, 1) and
15+
capture2 = input.regexpCapture(regexp, 2)
16+
}
17+
918
/** Companion module to the `AccessPath` class. */
1019
module AccessPath {
1120
/** A string that should be parsed as an access path. */
1221
abstract class Range extends string {
1322
bindingset[this]
1423
Range() { any() }
1524
}
25+
26+
/**
27+
* Parses an integer constant `n` or interval `n1..n2` (inclusive) and gets the value
28+
* of the constant or any value contained in the interval.
29+
*/
30+
bindingset[arg]
31+
int parseInt(string arg) {
32+
result = arg.toInt()
33+
or
34+
// Match "n1..n2"
35+
exists(string lo, string hi |
36+
regexpCaptureTwo(arg, "(-?\\d+)\\.\\.(-?\\d+)", lo, hi) and
37+
result = [lo.toInt() .. hi.toInt()]
38+
)
39+
}
40+
41+
/**
42+
* Parses a lower-bounded interval `n..` and gets the lower bound.
43+
*/
44+
bindingset[arg]
45+
int parseLowerBound(string arg) { result = arg.regexpCapture("(-?\\d+)\\.\\.", 1).toInt() }
46+
47+
/**
48+
* Parses an integer constant or interval (bounded or unbounded) that explicitly
49+
* references the arity, such as `N-1` or `N-3..N-1`.
50+
*
51+
* Note that expressions of form `N-x` will never resolve to a negative index,
52+
* even if `N` is zero (it will have no result in that case).
53+
*/
54+
bindingset[arg, arity]
55+
private int parseIntWithExplicitArity(string arg, int arity) {
56+
result >= 0 and // do not allow N-1 to resolve to a negative index
57+
exists(string lo |
58+
// N-x
59+
lo = arg.regexpCapture("N-(\\d+)", 1) and
60+
result = arity - lo.toInt()
61+
or
62+
// N-x..
63+
lo = arg.regexpCapture("N-(\\d+)\\.\\.", 1) and
64+
result = [arity - lo.toInt(), arity - 1]
65+
)
66+
or
67+
exists(string lo, string hi |
68+
// x..N-y
69+
regexpCaptureTwo(arg, "(-?\\d+)\\.\\.N-(\\d+)", lo, hi) and
70+
result = [lo.toInt() .. arity - hi.toInt()]
71+
or
72+
// N-x..N-y
73+
regexpCaptureTwo(arg, "N-(\\d+)\\.\\.N-(\\d+)", lo, hi) and
74+
result = [arity - lo.toInt() .. arity - hi.toInt()] and
75+
result >= 0
76+
or
77+
// N-x..y
78+
regexpCaptureTwo(arg, "N-(\\d+)\\.\\.(\\d+)", lo, hi) and
79+
result = [arity - lo.toInt() .. hi.toInt()] and
80+
result >= 0
81+
)
82+
}
83+
84+
/**
85+
* Parses an integer constant or interval (bounded or unbounded) and gets any
86+
* of the integers contained within (of which there may be infinitely many).
87+
*
88+
* Has no result for arguments involving an explicit arity, such as `N-1`.
89+
*/
90+
bindingset[arg, result]
91+
int parseIntUnbounded(string arg) {
92+
result = parseInt(arg)
93+
or
94+
result >= parseLowerBound(arg)
95+
}
96+
97+
/**
98+
* Parses an integer constant or interval (bounded or unbounded) that
99+
* may reference the arity of a call, such as `N-1` or `N-3..N-1`.
100+
*
101+
* Note that expressions of form `N-x` will never resolve to a negative index,
102+
* even if `N` is zero (it will have no result in that case).
103+
*/
104+
bindingset[arg, arity]
105+
int parseIntWithArity(string arg, int arity) {
106+
result = parseInt(arg)
107+
or
108+
result in [parseLowerBound(arg) .. arity - 1]
109+
or
110+
result = parseIntWithExplicitArity(arg, arity)
111+
}
16112
}
17113

18114
/** Gets the `n`th token on the access path as a string. */
@@ -53,7 +149,7 @@ class AccessPath extends string instanceof AccessPath::Range {
53149
* An access part token such as `Argument[1]` or `ReturnValue`, appearing in one or more access paths.
54150
*/
55151
class AccessPathToken extends string {
56-
AccessPathToken() { this = getRawToken(any(AccessPath path), _) }
152+
AccessPathToken() { this = getRawToken(_, _) }
57153

58154
private string getPart(int part) {
59155
result = this.regexpCapture("([^\\[]+)(?:\\[([^\\]]*)\\])?", part)
@@ -71,9 +167,16 @@ class AccessPathToken extends string {
71167
/** Gets the `n`th argument to this token, such as `x` or `y` from `Member[x,y]`. */
72168
string getArgument(int n) { result = this.getArgumentList().splitAt(",", n).trim() }
73169

170+
/** Gets the `n`th argument to this `name` token, such as `x` or `y` from `Member[x,y]`. */
171+
pragma[nomagic]
172+
string getArgument(string name, int n) { name = this.getName() and result = this.getArgument(n) }
173+
74174
/** Gets an argument to this token, such as `x` or `y` from `Member[x,y]`. */
75175
string getAnArgument() { result = this.getArgument(_) }
76176

177+
/** Gets an argument to this `name` token, such as `x` or `y` from `Member[x,y]`. */
178+
string getAnArgument(string name) { result = this.getArgument(name, _) }
179+
77180
/** Gets the number of arguments to this token, such as 2 for `Member[x,y]` or zero for `ReturnValue`. */
78181
int getNumArgument() { result = count(int n | exists(this.getArgument(n))) }
79182
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,21 @@ predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable f) { non
108108
* restricted to those `call`s for which a context might make a difference.
109109
*/
110110
DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) { none() }
111+
112+
private int parameterPosition() {
113+
result = [-1 .. any(DataFlowCallable c).getType().getNumParameter()]
114+
}
115+
116+
/** A parameter position represented by an integer. */
117+
class ParameterPosition extends int {
118+
ParameterPosition() { this = parameterPosition() }
119+
}
120+
121+
/** An argument position represented by an integer. */
122+
class ArgumentPosition extends int {
123+
ArgumentPosition() { this = parameterPosition() }
124+
}
125+
126+
/** Holds if arguments at position `apos` match parameters at position `ppos`. */
127+
pragma[inline]
128+
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) { ppos = apos }

0 commit comments

Comments
 (0)