Skip to content

Commit ff1a304

Browse files
author
Dean Karn
authored
Fix out-of-range exception (#46)
Fixed out-of-range exception. Fixes #45
1 parent 5c5278d commit ff1a304

File tree

4 files changed

+66
-43
lines changed

4 files changed

+66
-43
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package form
22
============
3-
<img align="right" src="https://raw.githubusercontent.com/go-playground/form/master/logo.jpg">![Project status](https://img.shields.io/badge/version-4.1.0-green.svg)
3+
<img align="right" src="https://raw.githubusercontent.com/go-playground/form/master/logo.jpg">![Project status](https://img.shields.io/badge/version-4.1.1-green.svg)
44
[![Build Status](https://travis-ci.org/go-playground/form.svg?branch=master)](https://travis-ci.org/go-playground/form)
55
[![Coverage Status](https://coveralls.io/repos/github/go-playground/form/badge.svg?branch=master)](https://coveralls.io/github/go-playground/form?branch=master)
66
[![Go Report Card](https://goreportcard.com/badge/github.com/go-playground/form)](https://goreportcard.com/report/github.com/go-playground/form)

benchmarks/benchmarks.md

+23-22
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,31 @@
11
## Benchmarks
22

3-
All Benchmarks Last Run Feb 2, 2019
3+
All Benchmarks Last Run Nov 17, 2019
44

5-
Run on MacBook Pro (15-inch, 2017) using go version go1.11.5 darwin/amd64
5+
Run on MacBook Pro (15-inch, 2017) using go version go1.13.4 darwin/amd64
66
go test -run=NONE -bench=. -benchmem=true
77

88
### go-playground/form
99
```go
10-
BenchmarkSimpleUserDecodeStruct-8 5000000 255 ns/op 64 B/op 1 allocs/op
11-
BenchmarkSimpleUserDecodeStructParallel-8 20000000 77.1 ns/op 64 B/op 1 allocs/op
12-
BenchmarkSimpleUserEncodeStruct-8 2000000 625 ns/op 485 B/op 10 allocs/op
13-
BenchmarkSimpleUserEncodeStructParallel-8 10000000 207 ns/op 485 B/op 10 allocs/op
14-
BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8 2000000 768 ns/op 96 B/op 1 allocs/op
15-
BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8 10000000 221 ns/op 96 B/op 1 allocs/op
16-
BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8 500000 3192 ns/op 2977 B/op 35 allocs/op
17-
BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8 1000000 1011 ns/op 2977 B/op 35 allocs/op
18-
BenchmarkComplexArrayDecodeStructAllTypes-8 100000 13269 ns/op 2248 B/op 121 allocs/op
19-
BenchmarkComplexArrayDecodeStructAllTypesParallel-8 500000 3758 ns/op 2249 B/op 121 allocs/op
20-
BenchmarkComplexArrayEncodeStructAllTypes-8 200000 10728 ns/op 7112 B/op 104 allocs/op
21-
BenchmarkComplexArrayEncodeStructAllTypesParallel-8 500000 3305 ns/op 7113 B/op 104 allocs/op
22-
BenchmarkComplexMapDecodeStructAllTypes-8 100000 17331 ns/op 5306 B/op 130 allocs/op
23-
BenchmarkComplexMapDecodeStructAllTypesParallel-8 300000 4901 ns/op 5309 B/op 130 allocs/op
24-
BenchmarkComplexMapEncodeStructAllTypes-8 100000 11226 ns/op 6970 B/op 129 allocs/op
25-
BenchmarkComplexMapEncodeStructAllTypesParallel-8 500000 3418 ns/op 6970 B/op 129 allocs/op
26-
BenchmarkDecodeNestedStruct-8 500000 2448 ns/op 384 B/op 14 allocs/op
27-
BenchmarkDecodeNestedStructParallel-8 2000000 736 ns/op 384 B/op 14 allocs/op
28-
BenchmarkEncodeNestedStruct-8 1000000 1468 ns/op 693 B/op 16 allocs/op
29-
BenchmarkEncodeNestedStructParallel-8 3000000 467 ns/op 693 B/op 16 allocs/op
10+
BenchmarkSimpleUserDecodeStruct-8 4447569 255 ns/op 64 B/op 1 allocs/op
11+
BenchmarkSimpleUserDecodeStructParallel-8 14087551 77.2 ns/op 64 B/op 1 allocs/op
12+
BenchmarkSimpleUserEncodeStruct-8 1863354 645 ns/op 485 B/op 10 allocs/op
13+
BenchmarkSimpleUserEncodeStructParallel-8 5554753 208 ns/op 485 B/op 10 allocs/op
14+
BenchmarkPrimitivesDecodeStructAllPrimitivesTypes-8 1345276 881 ns/op 96 B/op 1 allocs/op
15+
BenchmarkPrimitivesDecodeStructAllPrimitivesTypesParallel-8 4729965 259 ns/op 96 B/op 1 allocs/op
16+
BenchmarkPrimitivesEncodeStructAllPrimitivesTypes-8 303967 3331 ns/op 2977 B/op 35 allocs/op
17+
BenchmarkPrimitivesEncodeStructAllPrimitivesTypesParallel-8 1094600 1077 ns/op 2978 B/op 35 allocs/op
18+
BenchmarkComplexArrayDecodeStructAllTypes-8 76928 14567 ns/op 2248 B/op 121 allocs/op
19+
BenchmarkComplexArrayDecodeStructAllTypesParallel-8 292060 4355 ns/op 2249 B/op 121 allocs/op
20+
BenchmarkComplexArrayEncodeStructAllTypes-8 94536 11334 ns/op 7113 B/op 104 allocs/op
21+
BenchmarkComplexArrayEncodeStructAllTypesParallel-8 298318 3633 ns/op 7112 B/op 104 allocs/op
22+
BenchmarkComplexMapDecodeStructAllTypes-8 58084 18635 ns/op 5306 B/op 130 allocs/op
23+
BenchmarkComplexMapDecodeStructAllTypesParallel-8 187159 5454 ns/op 5308 B/op 130 allocs/op
24+
BenchmarkComplexMapEncodeStructAllTypes-8 101962 11763 ns/op 6971 B/op 129 allocs/op
25+
BenchmarkComplexMapEncodeStructAllTypesParallel-8 312925 4185 ns/op 6970 B/op 129 allocs/op
26+
BenchmarkDecodeNestedStruct-8 469940 2547 ns/op 384 B/op 14 allocs/op
27+
BenchmarkDecodeNestedStructParallel-8 1486963 810 ns/op 384 B/op 14 allocs/op
28+
BenchmarkEncodeNestedStruct-8 796798 1501 ns/op 693 B/op 16 allocs/op
29+
BenchmarkEncodeNestedStructParallel-8 2290203 520 ns/op 693 B/op 16 allocs/op
30+
3031
```

decoder.go

+13-20
Original file line numberDiff line numberDiff line change
@@ -28,24 +28,19 @@ func (d *decoder) setError(namespace []byte, err error) {
2828
if d.errs == nil {
2929
d.errs = make(DecodeErrors)
3030
}
31-
3231
d.errs[string(namespace)] = err
3332
}
3433

3534
func (d *decoder) findAlias(ns string) *recursiveData {
36-
3735
for i := 0; i < len(d.dm); i++ {
38-
3936
if d.dm[i].alias == ns {
4037
return d.dm[i]
4138
}
4239
}
43-
4440
return nil
4541
}
4642

4743
func (d *decoder) parseMapData() {
48-
4944
// already parsed
5045
if len(d.dm) > 0 {
5146
return
@@ -153,7 +148,6 @@ func (d *decoder) traverseStruct(v reflect.Value, typ reflect.Type, namespace []
153148
}
154149

155150
for _, f := range s.fields {
156-
157151
namespace = namespace[:l]
158152

159153
if f.isAnonymous {
@@ -202,28 +196,27 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
202196
}
203197
switch kind {
204198
case reflect.Interface:
205-
if !ok {
199+
if !ok || idx == len(arr) {
206200
return
207201
}
208202
v.Set(reflect.ValueOf(arr[idx]))
209203
set = true
210204

211205
case reflect.Ptr:
212-
213206
newVal := reflect.New(v.Type().Elem())
214207
if set = d.setFieldByType(newVal.Elem(), namespace, idx); set {
215208
v.Set(newVal)
216209
}
217210

218211
case reflect.String:
219-
if !ok {
212+
if !ok || idx == len(arr) {
220213
return
221214
}
222215
v.SetString(arr[idx])
223216
set = true
224217

225218
case reflect.Uint, reflect.Uint64:
226-
if !ok || len(arr[idx]) == 0 {
219+
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
227220
return
228221
}
229222
var u64 uint64
@@ -235,7 +228,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
235228
set = true
236229

237230
case reflect.Uint8:
238-
if !ok || len(arr[idx]) == 0 {
231+
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
239232
return
240233
}
241234
var u64 uint64
@@ -247,7 +240,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
247240
set = true
248241

249242
case reflect.Uint16:
250-
if !ok || len(arr[idx]) == 0 {
243+
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
251244
return
252245
}
253246
var u64 uint64
@@ -259,7 +252,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
259252
set = true
260253

261254
case reflect.Uint32:
262-
if !ok || len(arr[idx]) == 0 {
255+
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
263256
return
264257
}
265258
var u64 uint64
@@ -271,7 +264,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
271264
set = true
272265

273266
case reflect.Int, reflect.Int64:
274-
if !ok || len(arr[idx]) == 0 {
267+
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
275268
return
276269
}
277270
var i64 int64
@@ -283,7 +276,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
283276
set = true
284277

285278
case reflect.Int8:
286-
if !ok || len(arr[idx]) == 0 {
279+
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
287280
return
288281
}
289282
var i64 int64
@@ -295,7 +288,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
295288
set = true
296289

297290
case reflect.Int16:
298-
if !ok || len(arr[idx]) == 0 {
291+
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
299292
return
300293
}
301294
var i64 int64
@@ -307,7 +300,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
307300
set = true
308301

309302
case reflect.Int32:
310-
if !ok || len(arr[idx]) == 0 {
303+
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
311304
return
312305
}
313306
var i64 int64
@@ -319,7 +312,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
319312
set = true
320313

321314
case reflect.Float32:
322-
if !ok || len(arr[idx]) == 0 {
315+
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
323316
return
324317
}
325318
var f float64
@@ -331,7 +324,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
331324
set = true
332325

333326
case reflect.Float64:
334-
if !ok || len(arr[idx]) == 0 {
327+
if !ok || idx == len(arr) || len(arr[idx]) == 0 {
335328
return
336329
}
337330
var f float64
@@ -343,7 +336,7 @@ func (d *decoder) setFieldByType(current reflect.Value, namespace []byte, idx in
343336
set = true
344337

345338
case reflect.Bool:
346-
if !ok {
339+
if !ok || idx == len(arr) {
347340
return
348341
}
349342
var b bool

decoder_test.go

+29
Original file line numberDiff line numberDiff line change
@@ -1656,3 +1656,32 @@ func TestDecoder_RegisterCustomTypeFunc(t *testing.T) {
16561656

16571657
Equal(t, v.Slice, []customString{"customv1", "customv2"})
16581658
}
1659+
1660+
func TestDecoder_EmptyArrayString(t *testing.T) {
1661+
type T1 struct {
1662+
F1 string `form:"F1"`
1663+
}
1664+
in := url.Values{
1665+
"F1": []string{},
1666+
}
1667+
1668+
v := new(T1)
1669+
1670+
d := NewDecoder()
1671+
err := d.Decode(v, in)
1672+
Equal(t, err, nil)
1673+
}
1674+
1675+
func TestDecoder_EmptyArrayBool(t *testing.T) {
1676+
type T1 struct {
1677+
F1 bool `form:"F1"`
1678+
}
1679+
in := url.Values{
1680+
"F1": []string{},
1681+
}
1682+
1683+
v := new(T1)
1684+
d := NewDecoder()
1685+
err := d.Decode(v, in)
1686+
Equal(t, err, nil)
1687+
}

0 commit comments

Comments
 (0)