Skip to content

Commit

Permalink
Handle invalid Slice/Array indexes better (#61)
Browse files Browse the repository at this point in the history
  • Loading branch information
deankarn authored Jul 13, 2023
1 parent ff1560b commit 8785d3c
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 70 deletions.
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")
}

0 comments on commit 8785d3c

Please sign in to comment.