Skip to content
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

Handle invalid Slice/Array indexes better #61

Merged
merged 4 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,20 @@ jobs:
test:
strategy:
matrix:
go-version: [1.15.x, 1.16.x]
go-version: [1.17.x, 1.20.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Install Go
uses: actions/setup-go@v2
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}

- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Restore Cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ~/go/pkg/mod
key: ${{ runner.os }}-v1-go-${{ hashFiles('**/go.sum') }}
Expand All @@ -32,7 +32,7 @@ jobs:
run: go test -race -covermode=atomic -coverprofile="profile.cov" ./...

- name: Send Coverage
if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.16.x'
if: matrix.os == 'ubuntu-latest' && matrix.go-version == '1.20.x'
uses: shogo82148/actions-goveralls@v1
with:
path-to-profile: profile.cov
Expand All @@ -41,8 +41,8 @@ jobs:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
uses: golangci/golangci-lint-action@v3
with:
version: v1.37.1
version: latest
26 changes: 0 additions & 26 deletions .travis.yml

This file was deleted.

13 changes: 13 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
all: lint test bench

lint:
golangci-lint run --timeout 5m

test:
go test -covermode=atomic -race ./...

bench:
go test -bench=. -benchmem ./...

.PHONY: test lint bench
.DEFAULT_GOAL := all
60 changes: 25 additions & 35 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package form
============
<img align="right" src="https://raw.githubusercontent.com/go-playground/form/master/logo.jpg">![Project status](https://img.shields.io/badge/version-4.2.0-green.svg)
<img align="right" src="https://raw.githubusercontent.com/go-playground/form/master/logo.jpg">![Project status](https://img.shields.io/badge/version-4.2.1-green.svg)
[![Build Status](https://github.com/go-playground/form/actions/workflows/workflow.yml/badge.svg)](https://github.com/go-playground/form/actions/workflows/workflow.yml)
[![Coverage Status](https://coveralls.io/repos/github/go-playground/form/badge.svg?branch=master)](https://coveralls.io/github/go-playground/form?branch=master)
[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/form)](https://goreportcard.com/report/github.com/go-playground/form)
Expand Down Expand Up @@ -277,36 +277,35 @@ Field []*string{nil, nil, &i}

Benchmarks
------
###### Run on MacBook Pro (15-inch, 2017) using go version go1.10.1 darwin/amd64
###### Run on M1 MacBook Pro using go version go1.20.6 darwin/amd64

NOTE: the 1 allocation and B/op in the first 4 decodes is actually the struct allocating when passing it in, so primitives are actually zero allocation.

```go
go test -run=NONE -bench=. -benchmem=true
go test -run=NONE -bench=. -benchmem=true ./...
goos: darwin
goarch: amd64
pkg: github.com/go-playground/form/benchmarks

BenchmarkSimpleUserDecodeStruct-8 5000000 236 ns/op 64 B/op 1 allocs/op
BenchmarkSimpleUserDecodeStructParallel-8 20000000 82.1 ns/op 64 B/op 1 allocs/op
BenchmarkSimpleUserEncodeStruct-8 2000000 627 ns/op 485 B/op 10 allocs/op
BenchmarkSimpleUserEncodeStructParallel-8 10000000 223 ns/op 485 B/op 10 allocs/op
BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8 2000000 724 ns/op 96 B/op 1 allocs/op
BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8 10000000 246 ns/op 96 B/op 1 allocs/op
BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8 500000 3187 ns/op 2977 B/op 36 allocs/op
BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8 1000000 1106 ns/op 2977 B/op 36 allocs/op
BenchmarkComplexArrayDecodeStructAllTypes-8 100000 13748 ns/op 2248 B/op 121 allocs/op
BenchmarkComplexArrayDecodeStructAllTypesParallel-8 500000 4313 ns/op 2249 B/op 121 allocs/op
BenchmarkComplexArrayEncodeStructAllTypes-8 200000 10758 ns/op 7113 B/op 104 allocs/op
BenchmarkComplexArrayEncodeStructAllTypesParallel-8 500000 3532 ns/op 7113 B/op 104 allocs/op
BenchmarkComplexMapDecodeStructAllTypes-8 100000 17644 ns/op 5305 B/op 130 allocs/op
BenchmarkComplexMapDecodeStructAllTypesParallel-8 300000 5470 ns/op 5308 B/op 130 allocs/op
BenchmarkComplexMapEncodeStructAllTypes-8 200000 11155 ns/op 6971 B/op 129 allocs/op
BenchmarkComplexMapEncodeStructAllTypesParallel-8 500000 3768 ns/op 6971 B/op 129 allocs/op
BenchmarkDecodeNestedStruct-8 500000 2462 ns/op 384 B/op 14 allocs/op
BenchmarkDecodeNestedStructParallel-8 2000000 814 ns/op 384 B/op 14 allocs/op
BenchmarkEncodeNestedStruct-8 1000000 1483 ns/op 693 B/op 16 allocs/op
BenchmarkEncodeNestedStructParallel-8 3000000 525 ns/op 693 B/op 16 allocs/op
goarch: arm64
pkg: github.com/go-playground/form/v4/benchmarks
BenchmarkSimpleUserDecodeStruct-8 8704111 121.1 ns/op 64 B/op 1 allocs/op
BenchmarkSimpleUserDecodeStructParallel-8 35916134 32.89 ns/op 64 B/op 1 allocs/op
BenchmarkSimpleUserEncodeStruct-8 3746173 320.7 ns/op 485 B/op 10 allocs/op
BenchmarkSimpleUserEncodeStructParallel-8 7293147 180.0 ns/op 485 B/op 10 allocs/op
BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8 2993259 400.5 ns/op 96 B/op 1 allocs/op
BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8 13023300 97.70 ns/op 96 B/op 1 allocs/op
BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8 643202 1767 ns/op 2977 B/op 35 allocs/op
BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8 1000000 1202 ns/op 2978 B/op 35 allocs/op
BenchmarkComplexArrayDecodeStructAllTypes-8 172630 6822 ns/op 2008 B/op 121 allocs/op
BenchmarkComplexArrayDecodeStructAllTypesParallel-8 719788 1735 ns/op 2009 B/op 121 allocs/op
BenchmarkComplexArrayEncodeStructAllTypes-8 197052 5839 ns/op 7087 B/op 104 allocs/op
BenchmarkComplexArrayEncodeStructAllTypesParallel-8 348039 3247 ns/op 7089 B/op 104 allocs/op
BenchmarkComplexMapDecodeStructAllTypes-8 139246 8550 ns/op 5313 B/op 130 allocs/op
BenchmarkComplexMapDecodeStructAllTypesParallel-8 409018 3143 ns/op 5317 B/op 130 allocs/op
BenchmarkComplexMapEncodeStructAllTypes-8 208833 5515 ns/op 4257 B/op 103 allocs/op
BenchmarkComplexMapEncodeStructAllTypesParallel-8 523833 2182 ns/op 4258 B/op 103 allocs/op
BenchmarkDecodeNestedStruct-8 807690 1408 ns/op 344 B/op 14 allocs/op
BenchmarkDecodeNestedStructParallel-8 3409441 359.6 ns/op 344 B/op 14 allocs/op
BenchmarkEncodeNestedStruct-8 1488520 803.6 ns/op 653 B/op 16 allocs/op
BenchmarkEncodeNestedStructParallel-8 3570204 346.6 ns/op 653 B/op 16 allocs/op
```

Competitor benchmarks can be found [here](https://github.com/go-playground/form/blob/master/benchmarks/benchmarks.md)
Expand All @@ -319,15 +318,6 @@ Here is a list of software that compliments using this library post decoding.
* [Validator](https://github.com/go-playground/validator) - Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving.
* [mold](https://github.com/go-playground/mold) - Is a general library to help modify or set data within data structures and other objects.

Package Versioning
----------
I'm jumping on the vendoring bandwagon, you should vendor this package as I will not
be creating different version with gopkg.in like allot of my other libraries.

Why? because my time is spread pretty thin maintaining all of the libraries I have + LIFE,
it is so freeing not to worry about it and will help me keep pouring out bigger and better
things for you the community.

License
------
Distributed under MIT License, please see license file in code for more details.
6 changes: 5 additions & 1 deletion decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,11 @@ func (d *decoder) parseMapData() {
// no need to check for error, it will always pass
// as we have done the checking to ensure
// the value is a number ahead of time.
ke.ivalue, _ = strconv.Atoi(ke.value)
var err error
ke.ivalue, err = strconv.Atoi(ke.value)
if err != nil {
ke.ivalue = -1
}

if ke.ivalue > rd.sliceLen {
rd.sliceLen = ke.ivalue
Expand Down
27 changes: 27 additions & 0 deletions decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1909,3 +1909,30 @@ func TestDecoder_EmptyArrayBool(t *testing.T) {
err := d.Decode(v, in)
Equal(t, err, nil)
}

func TestDecoder_InvalidSliceIndex(t *testing.T) {
type PostsRequest struct {
PostIds []string
}
in := url.Values{
"PostIds[]": []string{"1", "2"},
}

v := new(PostsRequest)
d := NewDecoder()
err := d.Decode(v, in)
NotEqual(t, err, nil)
Equal(t, err.Error(), "Field Namespace:PostIds ERROR:invalid slice index ''")

// No error with proper name
type PostsRequest2 struct {
PostIds []string `form:"PostIds[]"`
}

v2 := new(PostsRequest2)
err = d.Decode(v2, in)
Equal(t, err, nil)
Equal(t, len(v2.PostIds), 2)
Equal(t, v2.PostIds[0], "1")
Equal(t, v2.PostIds[1], "2")
}