Skip to content

Commit 94e89f0

Browse files
fix: should panic when define duplicate field param in required_if (#1468)
## Fixes Or Enhances fix #1466 **Make sure that you've checked the boxes below before you submit PR:** - [x] Tests exist or have been written that cover this particular change. @go-playground/validator-maintainers --------- Co-authored-by: nodivbyzero <[email protected]>
1 parent 6905468 commit 94e89f0

File tree

3 files changed

+84
-10
lines changed

3 files changed

+84
-10
lines changed

baked_in.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,6 +1872,15 @@ func requiredIf(fl FieldLevel) bool {
18721872
if len(params)%2 != 0 {
18731873
panic(fmt.Sprintf("Bad param number for required_if %s", fl.FieldName()))
18741874
}
1875+
1876+
seen := make(map[string]struct{})
1877+
for i := 0; i < len(params); i += 2 {
1878+
if _, ok := seen[params[i]]; ok {
1879+
panic(fmt.Sprintf("Duplicate param %s for required_if %s", params[i], fl.FieldName()))
1880+
}
1881+
seen[params[i]] = struct{}{}
1882+
}
1883+
18751884
for i := 0; i < len(params); i += 2 {
18761885
if !requireCheckFieldValue(fl, params[i], params[i+1], false) {
18771886
return true

doc.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,7 @@ The field under validation must be present and not empty only if all
264264
the other specified fields are equal to the value following the specified
265265
field. For strings ensures value is not "". For slices, maps, pointers,
266266
interfaces, channels and functions ensures the value is not nil. For structs ensures value is not the zero value.
267+
Using the same field name multiple times in the parameters will result in a panic at runtime.
267268
268269
Usage: required_if
269270

validator_test.go

Lines changed: 74 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11099,6 +11099,49 @@ func TestRequiredIf(t *testing.T) {
1109911099
_ = validate.Struct(test3)
1110011100
}
1110111101

11102+
func TestRequiredIfDuplicateParams(t *testing.T) {
11103+
validate := New()
11104+
11105+
PanicMatches(t, func() {
11106+
type TestStruct struct {
11107+
Field1 string `validate:"required_if=Field2 value1 Field2 value2"`
11108+
Field2 string
11109+
}
11110+
test := TestStruct{
11111+
Field1: "",
11112+
Field2: "value1",
11113+
}
11114+
_ = validate.Struct(test)
11115+
}, "Duplicate param Field2 for required_if Field1")
11116+
11117+
PanicMatches(t, func() {
11118+
type TestStruct struct {
11119+
Field1 string `validate:"required_if=Field2 val1 Field3 val2 Field2 val3"`
11120+
Field2 string
11121+
Field3 string
11122+
}
11123+
test := TestStruct{
11124+
Field1: "",
11125+
Field2: "val1",
11126+
Field3: "val2",
11127+
}
11128+
_ = validate.Struct(test)
11129+
}, "Duplicate param Field2 for required_if Field1")
11130+
11131+
type TestStruct struct {
11132+
Field1 string `validate:"required_if=Field2 val1 Field3 val2"`
11133+
Field2 string
11134+
Field3 string
11135+
}
11136+
test := TestStruct{
11137+
Field1: "",
11138+
Field2: "val1",
11139+
Field3: "val2",
11140+
}
11141+
errs := validate.Struct(test)
11142+
NotEqual(t, errs, nil)
11143+
}
11144+
1110211145
func TestRequiredUnless(t *testing.T) {
1110311146
type Inner struct {
1110411147
Field *string
@@ -11169,19 +11212,40 @@ func TestRequiredUnless(t *testing.T) {
1116911212
AssertError(t, errs, "Field10", "Field10", "Field10", "Field10", "required_unless")
1117011213
AssertError(t, errs, "Field11", "Field11", "Field11", "Field11", "required_unless")
1117111214

11172-
defer func() {
11173-
if r := recover(); r == nil {
11174-
t.Errorf("test3 should have panicked!")
11215+
PanicMatches(t, func() {
11216+
test3 := struct {
11217+
Inner *Inner
11218+
Field1 string `validate:"required_unless=Inner.Field" json:"field_1"`
11219+
}{
11220+
Inner: &Inner{Field: &fieldVal},
1117511221
}
11176-
}()
11222+
_ = validate.Struct(test3)
11223+
}, "Bad param number for required_unless Field1")
1117711224

11178-
test3 := struct {
11179-
Inner *Inner
11180-
Field1 string `validate:"required_unless=Inner.Field" json:"field_1"`
11181-
}{
11182-
Inner: &Inner{Field: &fieldVal},
11225+
type DuplicateStruct struct {
11226+
Field1 string `validate:"required_unless=Field2 value1 Field2 value2"`
11227+
Field2 string
1118311228
}
11184-
_ = validate.Struct(test3)
11229+
test4 := DuplicateStruct{
11230+
Field1: "",
11231+
Field2: "value1",
11232+
}
11233+
errs = validate.Struct(test4)
11234+
Equal(t, errs, nil)
11235+
11236+
test5 := DuplicateStruct{
11237+
Field1: "",
11238+
Field2: "value2",
11239+
}
11240+
errs = validate.Struct(test5)
11241+
Equal(t, errs, nil)
11242+
11243+
test6 := DuplicateStruct{
11244+
Field1: "",
11245+
Field2: "value3",
11246+
}
11247+
errs = validate.Struct(test6)
11248+
NotEqual(t, errs, nil)
1118511249
}
1118611250

1118711251
func TestSkipUnless(t *testing.T) {

0 commit comments

Comments
 (0)