From 383d74ba4ff6ff34cccfe728b064fb298e24ab3b Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Tue, 10 Mar 2026 18:44:24 -0700 Subject: [PATCH] Fail to generate unsigned min and max for negative values --- .../cmd/validation-gen/validators/common.go | 9 +++++++++ .../cmd/validation-gen/validators/limits.go | 12 ++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/staging/src/k8s.io/code-generator/cmd/validation-gen/validators/common.go b/staging/src/k8s.io/code-generator/cmd/validation-gen/validators/common.go index 93cea458e84..9c05900dead 100644 --- a/staging/src/k8s.io/code-generator/cmd/validation-gen/validators/common.go +++ b/staging/src/k8s.io/code-generator/cmd/validation-gen/validators/common.go @@ -34,3 +34,12 @@ func rootTypeString(src, dst *types.Type) string { } return src.String() + " -> " + dst.String() } + +// isInt returns true if t is a uint type. +func isUnsignedInt(t *types.Type) bool { + switch t { + case types.Uint, types.Uint64, types.Uint32, types.Uint16, types.Byte: + return true + } + return false +} diff --git a/staging/src/k8s.io/code-generator/cmd/validation-gen/validators/limits.go b/staging/src/k8s.io/code-generator/cmd/validation-gen/validators/limits.go index 31c39d4b4e0..68cabb9a4e3 100644 --- a/staging/src/k8s.io/code-generator/cmd/validation-gen/validators/limits.go +++ b/staging/src/k8s.io/code-generator/cmd/validation-gen/validators/limits.go @@ -226,7 +226,8 @@ func (minimumTagValidator) GetValidations(context Context, tag codetags.Tag) (Va // This tag can apply to value and pointer fields, as well as typedefs // (which should never be pointers). We need to check the concrete type. - if t := util.NonPointer(util.NativeType(context.Type)); !types.IsInteger(t) { + t := util.NonPointer(util.NativeType(context.Type)) + if !types.IsInteger(t) { return result, fmt.Errorf("can only be used on integer types (%s)", rootTypeString(context.Type, t)) } @@ -234,6 +235,9 @@ func (minimumTagValidator) GetValidations(context Context, tag codetags.Tag) (Va if err != nil { return result, fmt.Errorf("failed to parse tag payload as int: %w", err) } + if isUnsignedInt(t) && intVal < 0 { + return result, fmt.Errorf("must be greater than or equal to zero for unsigned types (%s)", rootTypeString(context.Type, t)) + } result.AddFunction(Function(minimumTagName, DefaultFlags, minimumValidator, intVal)) return result, nil } @@ -274,7 +278,8 @@ func (maximumTagValidator) GetValidations(context Context, tag codetags.Tag) (Va // This tag can apply to value and pointer fields, as well as typedefs // (which should never be pointers). We need to check the concrete type. - if t := util.NonPointer(util.NativeType(context.Type)); !types.IsInteger(t) { + t := util.NonPointer(util.NativeType(context.Type)) + if !types.IsInteger(t) { return result, fmt.Errorf("can only be used on integer types (%s)", rootTypeString(context.Type, t)) } @@ -282,6 +287,9 @@ func (maximumTagValidator) GetValidations(context Context, tag codetags.Tag) (Va if err != nil { return result, fmt.Errorf("failed to parse tag payload as int: %w", err) } + if isUnsignedInt(t) && intVal < 0 { + return result, fmt.Errorf("must be greater than or equal to zero for unsigned types (%s)", rootTypeString(context.Type, t)) + } result.AddFunction(Function(maximumTagName, DefaultFlags, maximumValidator, intVal)) return result, nil }