From c43c234787d8fda254bf3143958641c210d722fa Mon Sep 17 00:00:00 2001 From: wln32 Date: Fri, 3 Jan 2025 11:56:48 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=BD=93=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E4=B8=BA=E5=9F=BA=E7=A1=80=E7=B1=BB=E5=9E=8B=E6=95=B0?= =?UTF-8?q?=E7=BB=84=E6=97=B6=EF=BC=8C=E5=AE=B9=E9=87=8F=E8=BF=87=E5=A4=A7?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E5=86=85=E5=AD=98=E6=B3=84=E6=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- util/gvalid/gvalid_validator_check_value.go | 54 +++++++++++++-------- util/gvalid/gvalid_z_unit_issue_test.go | 35 +++++++++++++ 2 files changed, 70 insertions(+), 19 deletions(-) diff --git a/util/gvalid/gvalid_validator_check_value.go b/util/gvalid/gvalid_validator_check_value.go index 759e97239af..469042d5664 100644 --- a/util/gvalid/gvalid_validator_check_value.go +++ b/util/gvalid/gvalid_validator_check_value.go @@ -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 + loopValid := false + switch in.Type.Elem().Kind() { + // []struct []map + case reflect.Struct, reflect.Map: + loopValid = true + case reflect.Ptr: + // []*struct + // []*int + loopValid = 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 loopValid { + 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 + } } } } diff --git a/util/gvalid/gvalid_z_unit_issue_test.go b/util/gvalid/gvalid_z_unit_issue_test.go index 38aea073937..5b4fa634190 100644 --- a/util/gvalid/gvalid_z_unit_issue_test.go +++ b/util/gvalid/gvalid_z_unit_issue_test.go @@ -9,6 +9,7 @@ package gvalid_test import ( "context" "fmt" + "runtime" "testing" "time" @@ -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, 100) + }) +} + +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 +} From bfa2f670b35677311ae22ef344ed72913512810c Mon Sep 17 00:00:00 2001 From: wln32 Date: Fri, 3 Jan 2025 18:01:52 +0800 Subject: [PATCH 2/3] up --- util/gvalid/gvalid_validator_check_value.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/util/gvalid/gvalid_validator_check_value.go b/util/gvalid/gvalid_validator_check_value.go index 469042d5664..970499e0469 100644 --- a/util/gvalid/gvalid_validator_check_value.go +++ b/util/gvalid/gvalid_validator_check_value.go @@ -287,21 +287,21 @@ func (v *Validator) doCheckValueRecursively(ctx context.Context, in doCheckValue } case reflect.Slice, reflect.Array: - loopValid := false + loop := false switch in.Type.Elem().Kind() { // []struct []map case reflect.Struct, reflect.Map: - loopValid = true + loop = true case reflect.Ptr: // []*struct // []*int - loopValid = true + loop = true } // 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 loopValid { + if loop { var array []interface{} if gjson.Valid(in.Value) { array = gconv.Interfaces(gconv.Bytes(in.Value)) From 90943fec8cb09dc735648918556aa617a700865c Mon Sep 17 00:00:00 2001 From: wln32 Date: Fri, 3 Jan 2025 19:53:44 +0800 Subject: [PATCH 3/3] up test --- util/gvalid/gvalid_z_unit_issue_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util/gvalid/gvalid_z_unit_issue_test.go b/util/gvalid/gvalid_z_unit_issue_test.go index 5b4fa634190..2bed169cba3 100644 --- a/util/gvalid/gvalid_z_unit_issue_test.go +++ b/util/gvalid/gvalid_z_unit_issue_test.go @@ -135,7 +135,7 @@ func Test_Issue4092(t *testing.T) { Run(context.Background()) t.Assert(err, "The Test value `6` is not in acceptable range: 1,2,3") allocMb := getMemAlloc() - t.AssertLE(allocMb, 100) + t.AssertLE(allocMb, 110) }) }