go-ozzo / ozzo-validation

An idiomatic Go (golang) validation package. Supports configurable and extensible validation rules (validators) using normal language constructs instead of error-prone struct tags.
MIT License
3.73k stars 224 forks source link

Stackoverflow validation.In() #133

Closed maeglindeveloper closed 3 years ago

maeglindeveloper commented 3 years ago

Hello everyone,

I'm actually facing an issue regarding the In() validation helper. I'm using it to validate a golang enumeration. Here is my enumeration definition & the Validate() method I defined for that "type":

type MyEnum string

const (
    MyTypeA MyEnum = "VALUE_A"
    MyTypeB MyEnum = "VALUE_B"
)

// Validate validates the enumeration value
func (m MyEnum) Validate() error {
    return validation.Validate(m, validation.In(
        MyTypeA,
        MyTypeB,
    ))
}

Then, I tried to execute the following tests:


func TestEnumerationValidation(t *testing.T) {
    m := "Test"
    if err := MyEnum(m).Validate(); err == nil {
        t.Fatal(err)
    }
    m2 := MyTypeA
    if err := m2.Validate(); err != nil {
        t.Fatal(err)
    }
}

The first part works, "Test" is not a valid value for an MyEnum but the second part of the test brings me to a stackoverflow error.

runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow

Here is a golang run link to test the code https://play.golang.org/p/rqoVqChoPJ_u

Am I doing something totally wrong ? Thanks for your collaboration team :)

qiangxue commented 3 years ago

This is because when you validate a value which implements Validatable, the Validate() method will be called automatically after passing the specified rules. See https://github.com/go-ozzo/ozzo-validation/blob/master/validation.go#L83 This will cause an infinite recursion.

To solve this issue, you should directly call In.Validate() within MyEnum.Validate().

maeglindeveloper commented 3 years ago

@qiangxue thanks ! it works definitively better now ;) !