Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
24 changes: 19 additions & 5 deletions baked_in.go
Original file line number Diff line number Diff line change
Expand Up @@ -2059,35 +2059,49 @@ func requireCheckFieldValue(

switch kind {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if value == "nil" {
return false
}
return field.Int() == asInt(value)

case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
if value == "nil" {
return false
}
return field.Uint() == asUint(value)

case reflect.Float32:
if value == "nil" {
return false
}
return field.Float() == asFloat32(value)

case reflect.Float64:
if value == "nil" {
return false
}
return field.Float() == asFloat64(value)

case reflect.Slice, reflect.Map:
if value == "nil" {
return field.IsNil()
}
return int64(field.Len()) == asInt(value)

case reflect.Array:
// Arrays can't be nil, so only compare lengths
if value == "nil" {
return false
}
return int64(field.Len()) == asInt(value)

case reflect.Bool:
return field.Bool() == (value == "true")

case reflect.Ptr:
if field.IsNil() {
return value == "nil"
}
// Handle non-nil pointers
return requireCheckFieldValue(fl, param, value, defaultNotFoundValue)
// extractTypeInternal dereferences non-nil pointers before reaching here,
// so this case is only reached when the pointer itself is nil.
return value == "nil"
}

// default reflect.String:
Expand Down
26 changes: 26 additions & 0 deletions validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13143,6 +13143,32 @@ func TestExcludedIf(t *testing.T) {
}
errs = validate.Struct(test12)
Equal(t, errs, nil)

// Issue #1320: excluded_if with "nil" param must not panic when comparing
// a non-nil pointer-to-numeric field against the literal "nil".
w13 := 10
r13 := 0
test13 := struct {
W *int
R *int `validate:"excluded_if=W nil"`
}{
W: &w13,
R: &r13,
}
errs = validate.Struct(test13)
Equal(t, errs, nil) // W is non-nil → excluded_if condition false → R not excluded → no error

// When W IS nil the excluded_if condition fires and R must be empty/nil to pass.
test14 := struct {
W *int
R *int `validate:"excluded_if=W nil"`
}{
W: nil,
R: nil,
}
errs = validate.Struct(test14)
Equal(t, errs, nil) // W is nil → excluded_if condition true → R must be nil/absent → passes

// Checks number of params in struct tag is correct
defer func() {
if r := recover(); r == nil {
Expand Down
Loading