-
Notifications
You must be signed in to change notification settings - Fork 425
fix(functional-pragmatist): replace make+len patterns to avoid CodeQL violations #23685
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -458,17 +458,18 @@ func TestFilter(t *testing.T) { | |||||
| package fp | ||||||
|
|
||||||
| // Map transforms each element in a slice | ||||||
| // Note: uses var+append to avoid CodeQL violations from make([]U, len(slice)) | ||||||
| func Map[T, U any](slice []T, fn func(T) U) []U { | ||||||
| result := make([]U, len(slice)) | ||||||
| for i, v := range slice { | ||||||
| result[i] = fn(v) | ||||||
| var result []U | ||||||
| for _, v := range slice { | ||||||
| result = append(result, fn(v)) | ||||||
| } | ||||||
| return result | ||||||
| } | ||||||
|
|
||||||
| // Filter returns elements that match the predicate | ||||||
| func Filter[T any](slice []T, fn func(T) bool) []T { | ||||||
| result := make([]T, 0, len(slice)) | ||||||
| var result []T | ||||||
| for _, v := range slice { | ||||||
| if fn(v) { | ||||||
| result = append(result, v) | ||||||
|
|
@@ -507,10 +508,10 @@ for _, name := range names { | |||||
| filters = append(filters, Filter{Name: name}) | ||||||
| } | ||||||
|
|
||||||
| // After: Immutable initialization | ||||||
| filters := make([]Filter, len(names)) | ||||||
| for i, name := range names { | ||||||
| filters[i] = Filter{Name: name} | ||||||
| // After: Immutable initialization using append | ||||||
| var filters []Filter | ||||||
| for _, name := range names { | ||||||
| filters = append(filters, Filter{Name: name}) | ||||||
| } | ||||||
|
Comment on lines
+511
to
515
|
||||||
| // Or even better if simple: | ||||||
| filters := sliceutil.Map(names, func(name string) Filter { | ||||||
|
|
@@ -570,7 +571,7 @@ activeItems := sliceutil.Filter(items, func(item Item) bool { return item.Active | |||||
| activeNames := sliceutil.Map(activeItems, func(item Item) string { return item.Name }) | ||||||
|
|
||||||
| // Or inline if it's clearer: | ||||||
| activeNames := make([]string, 0, len(items)) | ||||||
| var activeNames []string | ||||||
| for _, item := range items { | ||||||
|
Comment on lines
571
to
575
|
||||||
| if item.Active { | ||||||
| activeNames = append(activeNames, item.Name) | ||||||
|
|
@@ -1339,7 +1340,7 @@ func NewService(config *Config, cache *Cache) *Service | |||||
| - Go doesn't have built-in map/filter/reduce - that's okay! | ||||||
| - Inline loops are often clearer than generic helpers | ||||||
| - Use type parameters (generics) for helpers to avoid reflection | ||||||
| - Preallocate slices when size is known: `make([]T, len(input))` | ||||||
| - Avoid `make([]T, len(input))` and `make([]T, 0, len(input))` — use `var result []T` + `append` instead; CodeQL flags these patterns because the slice length/capacity is derived from user-controlled input, which can trigger incorrect memory allocation analysis | ||||||
|
||||||
| - Avoid `make([]T, len(input))` and `make([]T, 0, len(input))` — use `var result []T` + `append` instead; CodeQL flags these patterns because the slice length/capacity is derived from user-controlled input, which can trigger incorrect memory allocation analysis | |
| - When sizing slices or maps from user-controlled or otherwise untrusted input, validate and cap the size before calling `make` to avoid uncontrolled allocations and potential DoS; preallocating with `make([]T, len(input))` or `make([]T, 0, len(input))` is fine when `len(input)` comes from trusted, bounded, or already-validated data |
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.
The updated Map example uses a nil slice (
var result []U) and appends into it. This changes the empty-input behavior vs the previousmake([]U, len(slice)):Map([]T{}, ...)will now returnnilinstead of a non-nil empty slice, which can affect callers (e.g., JSONnullvs[],reflect.DeepEqual, or equality assertions). If you want to keep the prior semantics while still avoiding capacity/length derived from the input, consider initializing to an empty (non-nil) slice without usinglen(slice)for sizing, or explicitly documenting the nil-vs-empty behavior change in the guidance.This issue also appears in the following locations of the same file: