-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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
feat: static checking for common bug patterns #10190
Comments
one simple query to detect iterations over maps:
In Cosmos SDK, there are 59 cases: https://lgtm.com/query/5686749966483880627/ -- FYI @ryanchristo @robert-zaremba -- it may be good to go over them to check they are harmless. I guess that query could be added to CI as it is, but alternatively, we can also refine it for a higher precision: https://codeql.github.com/docs/codeql-language-guides/modeling-data-flow-in-go-libraries/ The more precise query would be something like: find all iterations over map which are one of these options:
|
cc @odeke-em |
besides map iteration, I guess it'd be good to have queries to scan for other sources of non-determinism -- as with https://forum.cosmos.network/t/cosmos-sdk-vulnerability-retrospective-security-advisory-jackfruit-october-12-2021/5349 -- |
I tried to exclude test and telemetry usage of
There are 5 results in the current master: https://lgtm.com/query/1044813113192157603/ including that problem in authz |
There are no results in the current master:
but I verified that running this query locally on a DB built from SDK v0.41.4, it'll have 33 findings. |
In some SDK projects, floating point operations were parts of bugs, so it may be good to flag them too:
|
I tried to collect all the queries in this repo: https://github.com/crypto-com/cosmos-sdk-codeql |
Thanks for the issue. Anything in client, cli and tests can be ignored. This is definitely needed and please feel free to create a PR. It seams that all / most of them are false positives. As Bez noted in the chat, we will need some statement to ignore that false positives. PS: this is related to : #10329 |
Closes cosmos#10190 added a basic GH Action pipeline for CodeQL that checks general security and code quality issues plus a few custom queries for Cosmos SDK defined in https://github.com/crypto-com/cosmos-sdk-codeql
… value This pass exists to curtail non-determinism in the cosmos-sdk which stemmed from iterating over maps during upgrades and that caused a chaotic debug for weeks. With this change, we'll now enforce and report failed iterations, with the rule being that a map in a range should involve ONLY one of these 2 operations: * for k := range m { delete(m, k) } for fast map clearing * for k := range m { keys = append(keys, k) } to retrieve keys & sort thus we shall get this report: ```shell [gosec] 2021/11/09 03:18:57 Rule error: *sdk.mapRanging => the value in the range statement should be nil: want: for key := range m (main.go:19) [gosec] 2021/11/09 03:18:57 Rule error: *sdk.mapRanging => the value in the range statement should be nil: want: for key := range m (main.go:27) ``` from the code below: ```go package main func main() { m := map[string]int{ "a": 0, "b": 1, "c": 2, "d": 3, } makeMap := func() map[string]string { return nil } keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) } values := make([]int, 0, len(m)) for _, value := range m { values = append(values, value) } type kv struct { k, v interface{} } kvL := make([]*kv, 0, len(m)) for k, v := range m { kvL = append(kvL, &kv{k, v}) } for k := range m { delete(m, k) } for k := range makeMap() { delete(m, k) } for k := range do() { delete(m, k) } } func do() map[string]string { return nil } ``` Updates cosmos/cosmos-sdk#10190
… value This pass exists to curtail non-determinism in the cosmos-sdk which stemmed from iterating over maps during upgrades and that caused a chaotic debug for weeks. With this change, we'll now enforce and report failed iterations, with the rule being that a map in a range should involve ONLY one of these 2 operations: * for k := range m { delete(m, k) } for fast map clearing * for k := range m { keys = append(keys, k) } to retrieve keys & sort thus we shall get this report: ```shell [gosec] 2021/11/09 03:18:57 Rule error: *sdk.mapRanging => the value in the range statement should be nil: want: for key := range m (main.go:19) [gosec] 2021/11/09 03:18:57 Rule error: *sdk.mapRanging => the value in the range statement should be nil: want: for key := range m (main.go:27) ``` from the code below: ```go package main func main() { m := map[string]int{ "a": 0, "b": 1, "c": 2, "d": 3, } makeMap := func() map[string]string { return nil } keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) } values := make([]int, 0, len(m)) for _, value := range m { values = append(values, value) } type kv struct { k, v interface{} } kvL := make([]*kv, 0, len(m)) for k, v := range m { kvL = append(kvL, &kv{k, v}) } for k := range m { delete(m, k) } for k := range makeMap() { delete(m, k) } for k := range do() { delete(m, k) } } func do() map[string]string { return nil } ``` Updates cosmos/cosmos-sdk#10190
… value This pass exists to curtail non-determinism in the cosmos-sdk which stemmed from iterating over maps during upgrades and that caused a chaotic debug for weeks. With this change, we'll now enforce and report failed iterations, with the rule being that a map in a range should involve ONLY one of these 2 operations: * for k := range m { delete(m, k) } for fast map clearing * for k := range m { keys = append(keys, k) } to retrieve keys & sort thus we shall get this report: ```shell [gosec] 2021/11/09 03:18:57 Rule error: *sdk.mapRanging => the value in the range statement should be nil: want: for key := range m (main.go:19) [gosec] 2021/11/09 03:18:57 Rule error: *sdk.mapRanging => the value in the range statement should be nil: want: for key := range m (main.go:27) ``` from the code below: ```go package main func main() { m := map[string]int{ "a": 0, "b": 1, "c": 2, "d": 3, } makeMap := func() map[string]string { return nil } keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) } values := make([]int, 0, len(m)) for _, value := range m { values = append(values, value) } type kv struct { k, v interface{} } kvL := make([]*kv, 0, len(m)) for k, v := range m { kvL = append(kvL, &kv{k, v}) } for k := range m { delete(m, k) } for k := range makeMap() { delete(m, k) } for k := range do() { delete(m, k) } } func do() map[string]string { return nil } ``` Updates cosmos/cosmos-sdk#10190
We've got unreleased code in a private repo (collabo between Informal Systems * Orijtech Inc) that has a static analyzer/pass that'll detect when maps are being iterated over with values and enforce keys must be iterated upon then perhaps sorted. Kindly cc-ing @ebuchman |
… value This pass exists to curtail non-determinism in the cosmos-sdk which stemmed from iterating over maps during upgrades and that caused a chaotic debug for weeks. With this change, we'll now enforce and report failed iterations, with the rule being that a map in a range should involve ONLY one of these 2 operations: * for k := range m { delete(m, k) } for fast map clearing * for k := range m { keys = append(keys, k) } to retrieve keys & sort thus we shall get this report: ```shell [gosec] 2021/11/09 03:18:57 Rule error: *sdk.mapRanging => the value in the range statement should be nil: want: for key := range m (main.go:19) [gosec] 2021/11/09 03:18:57 Rule error: *sdk.mapRanging => the value in the range statement should be nil: want: for key := range m (main.go:27) ``` from the code below: ```go package main func main() { m := map[string]int{ "a": 0, "b": 1, "c": 2, "d": 3, } makeMap := func() map[string]string { return nil } keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) } values := make([]int, 0, len(m)) for _, value := range m { values = append(values, value) } type kv struct { k, v interface{} } kvL := make([]*kv, 0, len(m)) for k, v := range m { kvL = append(kvL, &kv{k, v}) } for k := range m { delete(m, k) } for k := range makeMap() { delete(m, k) } for k := range do() { delete(m, k) } } func do() map[string]string { return nil } ``` Updates cosmos/cosmos-sdk#10190
… value This pass exists to curtail non-determinism in the cosmos-sdk which stemmed from iterating over maps during upgrades and that caused a chaotic debug for weeks. With this change, we'll now enforce and report failed iterations, with the rule being that a map in a range should involve ONLY one of these 2 operations: * for k := range m { delete(m, k) } for fast map clearing * for k := range m { keys = append(keys, k) } to retrieve keys & sort thus we shall get this report: ```shell [gosec] 2021/11/09 03:18:57 Rule error: *sdk.mapRanging => the value in the range statement should be nil: want: for key := range m (main.go:19) [gosec] 2021/11/09 03:18:57 Rule error: *sdk.mapRanging => the value in the range statement should be nil: want: for key := range m (main.go:27) ``` from the code below: ```go package main func main() { m := map[string]int{ "a": 0, "b": 1, "c": 2, "d": 3, } makeMap := func() map[string]string { return nil } keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) } values := make([]int, 0, len(m)) for _, value := range m { values = append(values, value) } type kv struct { k, v interface{} } kvL := make([]*kv, 0, len(m)) for k, v := range m { kvL = append(kvL, &kv{k, v}) } for k := range m { delete(m, k) } for k := range makeMap() { delete(m, k) } for k := range do() { delete(m, k) } } func do() map[string]string { return nil } ``` Updates cosmos/cosmos-sdk#10190
## Description Closes: #10190 added a basic GH Action pipeline for CodeQL that checks general security and code quality issues plus a few custom queries for Cosmos SDK defined in https://github.com/crypto-com/cosmos-sdk-codeql --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [x] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [x] reviewed "Files changed" and left comments if necessary - [x] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
… value This pass exists to curtail non-determinism in the cosmos-sdk which stemmed from iterating over maps during upgrades and that caused a chaotic debug for weeks. With this change, we'll now enforce and report failed iterations, with the rule being that a map in a range should involve ONLY one of these 2 operations: * for k := range m { delete(m, k) } for fast map clearing * for k := range m { keys = append(keys, k) } to retrieve keys & sort thus we shall get this report: ```shell [gosec] 2021/11/09 03:18:57 Rule error: *sdk.mapRanging => the value in the range statement should be nil: want: for key := range m (main.go:19) [gosec] 2021/11/09 03:18:57 Rule error: *sdk.mapRanging => the value in the range statement should be nil: want: for key := range m (main.go:27) ``` from the code below: ```go package main func main() { m := map[string]int{ "a": 0, "b": 1, "c": 2, "d": 3, } makeMap := func() map[string]string { return nil } keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) } values := make([]int, 0, len(m)) for _, value := range m { values = append(values, value) } type kv struct { k, v interface{} } kvL := make([]*kv, 0, len(m)) for k, v := range m { kvL = append(kvL, &kv{k, v}) } for k := range m { delete(m, k) } for k := range makeMap() { delete(m, k) } for k := range do() { delete(m, k) } } func do() map[string]string { return nil } ``` Updates cosmos/cosmos-sdk#10189 Updates cosmos/cosmos-sdk#10188 Updates cosmos/cosmos-sdk#10190
… value This pass exists to curtail non-determinism in the cosmos-sdk which stemmed from iterating over maps during upgrades and that caused a chaotic debug for weeks. With this change, we'll now enforce and report failed iterations, with the rule being that a map in a range should involve ONLY one of these 2 operations: * for k := range m { delete(m, k) } for fast map clearing * for k := range m { keys = append(keys, k) } to retrieve keys & sort thus we shall get this report: ```shell [gosec] 2021/11/09 03:18:57 Rule error: *sdk.mapRanging => the value in the range statement should be nil: want: for key := range m (main.go:19) [gosec] 2021/11/09 03:18:57 Rule error: *sdk.mapRanging => the value in the range statement should be nil: want: for key := range m (main.go:27) ``` from the code below: ```go package main func main() { m := map[string]int{ "a": 0, "b": 1, "c": 2, "d": 3, } makeMap := func() map[string]string { return nil } keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) } values := make([]int, 0, len(m)) for _, value := range m { values = append(values, value) } type kv struct { k, v interface{} } kvL := make([]*kv, 0, len(m)) for k, v := range m { kvL = append(kvL, &kv{k, v}) } for k := range m { delete(m, k) } for k := range makeMap() { delete(m, k) } for k := range do() { delete(m, k) } } func do() map[string]string { return nil } ``` Updates cosmos/cosmos-sdk#10189 Updates cosmos/cosmos-sdk#10188 Updates cosmos/cosmos-sdk#10190
## Description Closes: cosmos#10190 added a basic GH Action pipeline for CodeQL that checks general security and code quality issues plus a few custom queries for Cosmos SDK defined in https://github.com/crypto-com/cosmos-sdk-codeql --- ### Author Checklist *All items are required. Please add a note to the item if the item is not applicable and please add links to any relevant follow up issues.* I have... - [x] included the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] added `!` to the type prefix if API or client breaking change - [x] targeted the correct branch (see [PR Targeting](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#pr-targeting)) - [x] provided a link to the relevant issue or specification - [ ] followed the guidelines for [building modules](https://github.com/cosmos/cosmos-sdk/blob/master/docs/building-modules) - [ ] included the necessary unit and integration [tests](https://github.com/cosmos/cosmos-sdk/blob/master/CONTRIBUTING.md#testing) - [ ] added a changelog entry to `CHANGELOG.md` - [ ] included comments for [documenting Go code](https://blog.golang.org/godoc) - [ ] updated the relevant documentation or specification - [x] reviewed "Files changed" and left comments if necessary - [x] confirmed all CI checks have passed ### Reviewers Checklist *All items are required. Please add a note if the item is not applicable and please add your handle next to the items reviewed if you only reviewed selected items.* I have... - [ ] confirmed the correct [type prefix](https://github.com/commitizen/conventional-commit-types/blob/v3.0.0/index.json) in the PR title - [ ] confirmed `!` in the type prefix if API or client breaking change - [ ] confirmed all author checklist items have been addressed - [ ] reviewed state machine logic - [ ] reviewed API design and naming - [ ] reviewed documentation is accurate - [ ] reviewed tests and test coverage - [ ] manually tested (if applicable)
Summary
It'd be good to add GH Action that would statically check for common bug patterns -- e.g. https://github.com/github/codeql-action
Problem Definition
There are a few bugs that resurfaced a few times in Cosmos SDK -- off the top of my head, I can think of:
It would be good to capture these sorts of bug patterns in static analysis tools, so that it's less likely to re-introduce them.
Related:
Proposal
Add CodeQL Github Action pipeline: https://github.com/github/codeql-action
and write a few custom CodeQL queries to capture common bugs from the past: https://codeql.github.com/docs/codeql-language-guides/codeql-for-go/
For Admin Use
The text was updated successfully, but these errors were encountered: