Skip to content

Commit 7aba81c

Browse files
authored
fix: resolve panic when using aliases with OR operator (#1507)
1 parent 4d600be commit 7aba81c

File tree

2 files changed

+80
-0
lines changed

2 files changed

+80
-0
lines changed

cache.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,24 @@ func (v *Validate) parseFieldTagsRecursive(tag string, fieldName string, alias s
289289
if wrapper, ok := v.validations[current.tag]; ok {
290290
current.fn = wrapper.fn
291291
current.runValidationWhenNil = wrapper.runValidationOnNil
292+
} else if aliasTag, isAlias := v.aliases[current.tag]; isAlias {
293+
aliasFirst, aliasLast := v.parseFieldTagsRecursive(aliasTag, fieldName, current.tag, true)
294+
295+
current.tag = aliasFirst.tag
296+
current.fn = aliasFirst.fn
297+
current.runValidationWhenNil = aliasFirst.runValidationWhenNil
298+
current.hasParam = aliasFirst.hasParam
299+
current.param = aliasFirst.param
300+
current.typeof = aliasFirst.typeof
301+
current.hasAlias = true
302+
303+
if aliasFirst.next != nil {
304+
nextInChain := current.next
305+
current.next = aliasFirst.next
306+
aliasLast.next = nextInChain
307+
aliasLast.isBlockEnd = false
308+
current = aliasLast
309+
}
292310
} else {
293311
panic(strings.TrimSpace(fmt.Sprintf(undefinedValidation, current.tag, fieldName)))
294312
}

validator_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,68 @@ func TestAliasTags(t *testing.T) {
696696
PanicMatches(t, func() { validate.RegisterAlias("exists!", "gt=5,lt=10") }, "Alias 'exists!' either contains restricted characters or is the same as a restricted tag needed for normal operation")
697697
}
698698

699+
func TestAliasWithOrOperator(t *testing.T) {
700+
validate := New()
701+
validate.RegisterAlias("customnum", "numeric")
702+
validate.RegisterAlias("customalpha", "alpha")
703+
validate.RegisterAlias("customgt5", "gt=5")
704+
705+
t.Run("numeric|iscolor", func(t *testing.T) {
706+
type S struct {
707+
F string `validate:"numeric|iscolor"`
708+
}
709+
Equal(t, validate.Struct(S{"#fff"}), nil)
710+
Equal(t, validate.Struct(S{"123"}), nil)
711+
NotEqual(t, validate.Struct(S{"invalid!"}), nil)
712+
})
713+
714+
t.Run("iscolor|numeric", func(t *testing.T) {
715+
type S struct {
716+
F string `validate:"iscolor|numeric"`
717+
}
718+
Equal(t, validate.Struct(S{"456"}), nil)
719+
Equal(t, validate.Struct(S{"rgb(255,0,0)"}), nil)
720+
})
721+
722+
t.Run("alpha|customnum", func(t *testing.T) {
723+
type S struct {
724+
F string `validate:"alpha|customnum"`
725+
}
726+
Equal(t, validate.Struct(S{"789"}), nil)
727+
Equal(t, validate.Struct(S{"abc"}), nil)
728+
})
729+
730+
t.Run("customnum|customalpha", func(t *testing.T) {
731+
type S struct {
732+
F string `validate:"customnum|customalpha"`
733+
}
734+
Equal(t, validate.Struct(S{"xyz"}), nil)
735+
})
736+
737+
t.Run("alpha|customnum|email", func(t *testing.T) {
738+
type S struct {
739+
F string `validate:"alpha|customnum|email"`
740+
}
741+
Equal(t, validate.Struct(S{"[email protected]"}), nil)
742+
})
743+
744+
t.Run("eq=0|customgt5", func(t *testing.T) {
745+
type S struct {
746+
F int `validate:"eq=0|customgt5"`
747+
}
748+
Equal(t, validate.Struct(S{0}), nil)
749+
Equal(t, validate.Struct(S{10}), nil)
750+
NotEqual(t, validate.Struct(S{3}), nil)
751+
})
752+
753+
t.Run("numeric|country_code", func(t *testing.T) {
754+
type S struct {
755+
F string `validate:"numeric|country_code"`
756+
}
757+
Equal(t, validate.Struct(S{"US"}), nil)
758+
})
759+
}
760+
699761
func TestNilValidator(t *testing.T) {
700762
type TestStruct struct {
701763
Test string `validate:"required"`

0 commit comments

Comments
 (0)