Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
54 changes: 35 additions & 19 deletions util/gvalid/gvalid_validator_check_value.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,26 +287,42 @@ func (v *Validator) doCheckValueRecursively(ctx context.Context, in doCheckValue
}

case reflect.Slice, reflect.Array:
var array []interface{}
if gjson.Valid(in.Value) {
array = gconv.Interfaces(gconv.Bytes(in.Value))
} else {
array = gconv.Interfaces(in.Value)
}
if len(array) == 0 {
return
loop := false
switch in.Type.Elem().Kind() {
// []struct []map
case reflect.Struct, reflect.Map:
loop = true
case reflect.Ptr:
// []*struct
// []*int
loop = true
}
for _, item := range array {
v.doCheckValueRecursively(ctx, doCheckValueRecursivelyInput{
Value: item,
Type: in.Type.Elem(),
Kind: in.Type.Elem().Kind(),
ErrorMaps: in.ErrorMaps,
ResultSequenceRules: in.ResultSequenceRules,
})
// Bail feature.
if v.bail && len(in.ErrorMaps) > 0 {
break
// When it is a base type array,
// there is no need for recursive loop validation,
// otherwise it will cause memory leakage
// https://github.com/gogf/gf/issues/4092
if loop {
var array []interface{}
if gjson.Valid(in.Value) {
array = gconv.Interfaces(gconv.Bytes(in.Value))
} else {
array = gconv.Interfaces(in.Value)
}
if len(array) == 0 {
return
}
for _, item := range array {
v.doCheckValueRecursively(ctx, doCheckValueRecursivelyInput{
Value: item,
Type: in.Type.Elem(),
Kind: in.Type.Elem().Kind(),
ErrorMaps: in.ErrorMaps,
ResultSequenceRules: in.ResultSequenceRules,
})
// Bail feature.
if v.bail && len(in.ErrorMaps) > 0 {
break
}
}
}
}
Expand Down
35 changes: 35 additions & 0 deletions util/gvalid/gvalid_z_unit_issue_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package gvalid_test
import (
"context"
"fmt"
"runtime"
"testing"
"time"

Expand Down Expand Up @@ -114,3 +115,37 @@ func Test_Issue3636(t *testing.T) {
)
})
}

// https://github.com/gogf/gf/issues/4092
func Test_Issue4092(t *testing.T) {
type Model struct {
Raw []byte `v:"required"`
Test []byte `v:"foreach|in:1,2,3"`
}
gtest.C(t, func(t *gtest.T) {
const kb = 1024
const mb = 1024 * kb
raw := make([]byte, 50*mb)
in := &Model{
Raw: raw,
Test: []byte{40, 5, 6},
}
err := g.Validator().
Data(in).
Run(context.Background())
t.Assert(err, "The Test value `6` is not in acceptable range: 1,2,3")
allocMb := getMemAlloc()
t.AssertLE(allocMb, 110)
})
}

func getMemAlloc() uint64 {
byteToMb := func(b uint64) uint64 {
return b / 1024 / 1024
}
var m runtime.MemStats
runtime.ReadMemStats(&m)
// For info on each, see: https://golang.org/pkg/runtime/#MemStats
alloc := byteToMb(m.Alloc)
return alloc
}
Loading