-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Go: fix models for built-in functions #16413
Conversation
Click to show differences in coveragegoGenerated file changes for go
- `Standard library <https://pkg.go.dev/std>`_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``",8,578,
+ `Standard library <https://pkg.go.dev/std>`_,"````, ``archive/*``, ``bufio``, ``bytes``, ``cmp``, ``compress/*``, ``container/*``, ``context``, ``crypto``, ``crypto/*``, ``database/*``, ``debug/*``, ``embed``, ``encoding``, ``encoding/*``, ``errors``, ``expvar``, ``flag``, ``fmt``, ``go/*``, ``hash``, ``hash/*``, ``html``, ``html/*``, ``image``, ``image/*``, ``index/*``, ``io``, ``io/*``, ``log``, ``log/*``, ``maps``, ``math``, ``math/*``, ``mime``, ``mime/*``, ``net``, ``net/*``, ``os``, ``os/*``, ``path``, ``path/*``, ``plugin``, ``reflect``, ``reflect/*``, ``regexp``, ``regexp/*``, ``slices``, ``sort``, ``strconv``, ``strings``, ``sync``, ``sync/*``, ``syscall``, ``syscall/*``, ``testing``, ``testing/*``, ``text/*``, ``time``, ``time/*``, ``unicode``, ``unicode/*``, ``unsafe``",8,581,
- Totals,,20,871,24
+ Totals,,20,874,24
- ,,,2,,,,,2
+ ,,,5,,,,,5 |
0a0d54d
to
95eeefd
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't reviewed the test changes, but the code changes look good to me.
@@ -455,8 +455,8 @@ module Public { | |||
CallNode getCallNode() { result = call } | |||
|
|||
override Type getType() { | |||
exists(Function f | f = call.getTarget() | | |||
result = f.getParameterType(f.getNumParameter() - 1) | |||
exists(SignatureType t | t = call.getCall().getCalleeType() | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
exists(SignatureType t | t = call.getCall().getCalleeType() | | |
// Note this differs from `call.getTarget()`'s parameter types for polymorphic builtins like `append`. | |
exists(SignatureType t | t = call.getCall().getCalleeType() | |
To check: are there old-school QL models relating to either function that are now duplicative or redundant? |
79cdec8
to
694c896
Compare
694c896
to
6100995
Compare
6100995
to
f7e6bf7
Compare
I've now updated this to remove the old-style models and make sure all tests changes are ones we expect/want. It's ready to review again. |
go/ql/lib/ext/builtin.model.yml
Outdated
- ["", "", False, "append", "", "", "Argument[1].ArrayElement", "ReturnValue.ArrayElement", "value", "manual"] | ||
- ["", "", False, "copy", "", "", "Argument[1].ArrayElement", "Argument[0].ArrayElement", "value", "manual"] | ||
- ["", "", False, "max", "", "", "Argument[0]", "ReturnValue", "value", "manual"] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Per https://pkg.go.dev/builtin#max min and max are variadic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, I hadn't realised that there could be more than two arguments. Although, despite what those docs say, if I try to implement the model like that then it doesn't work. It seems that the compiler has special-cased these functions, and they just have an invalid signature and aren't considered variadic. Maybe because of lack of generics originally stopping them from being implemented normally. I can get the type for the CallExpr
and for three arguments it's func(int, int, int) int
. It's a bit annoying, as we don't have a way of saying "any argument" in models-as-data (according to our docs, at least). I guess we could do 0..1000
. I'll experiment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I asked on the Gophers slack and someone pointed me to this comment. It turns out that min
and max
were only added in Go 1.21, and after some debate they decided to make them built-in functions because it's nicer to write max(a, b)
than Math.Max(a, b)
and they seem to provide a fundamental utility (though Go survived without it for a long time).
@@ -127,12 +127,10 @@ | |||
| main.go:64:7:64:18 | call to min | main.go:64:2:64:2 | definition of a | | |||
| main.go:64:11:64:11 | x | main.go:64:7:64:18 | call to min | | |||
| main.go:64:14:64:14 | y | main.go:64:7:64:18 | call to min | | |||
| main.go:64:17:64:17 | z | main.go:64:7:64:18 | call to min | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lost results due to min and max being variadic functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This has been fixed now.
@@ -3,13 +3,6 @@ | |||
| main.go:38:13:38:13 | 1 | main.go:38:7:38:20 | slice literal | | |||
| main.go:38:16:38:16 | 2 | main.go:38:7:38:20 | slice literal | | |||
| main.go:38:19:38:19 | 3 | main.go:38:7:38:20 | slice literal | | |||
| main.go:39:15:39:15 | s | main.go:39:8:39:25 | call to append | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're sure taint still works as expected here, just via different steps?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test, and the value flow counterpart, only show steps without any reads or stores. The model for append is now a value step with a store, so it isn't shown. The test in go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/test.go
still shows taint flow through append
.
dc4cbf2
to
31e3422
Compare
Although the documentation makes them look variadic (and generic), they are actually special-cased in the compiler. Like all built-in functions they don't have a signature type, but the type of `min(a, b, c)` is `func(int, int, int) int` and not `func(int, ...int) int`. Go doesn't allow open-ended ranges for argument indices in models-as-data specifications (though Ruby and Python do), so I've used `1..1000`.
31e3422
to
827d15a
Compare
Our model for
append
was wrong, asappend
is variadic. We were missing a model forcopy
. Here are the package docs and the relevant part of the spec.I had to fix two bugs which I made into separate PRs
And I fixed one bug in this PR which is hard to otherwise test for.
I also span out #16444 to make the value flow tests have the same results as the taint flow tests.