fix(parameters): handle uint64 schema validation at shared boundary - #10439
Conversation
CUE-generated uint64 schemas have Maximum = float64(MaxUint64) which overflows when kube-openapi converts to int64 internally. The same issue affects int64 schemas where float64(MaxInt64) rounds to 2^63. Fix at the shared ValidateDataWithSchema boundary so all callers (ComponentParameterAssignments, OpsDefinition, DataProtection ActionSet) are protected. Detection uses CUE-generated bounds (Minimum >= 0, Maximum > 2^63) since CUE does not set Format on integer schemas. Addresses leon-ape P1 (preserve uint64 range) and P2 (shared boundary) review comments on #10412. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Auto Cherry-pick Instructions CLA Recheck Instructions |
| } | ||
| out := schema.DeepCopy() | ||
| for k, prop := range out.Properties { | ||
| if prop.Type == "integer" && prop.Maximum != nil && *prop.Maximum >= math.Exp2(63) { |
There was a problem hiding this comment.
This weakens the shared OpenAPI validation contract for any integer schema whose user-declared maximum is above the signed int64 range. For example, an OpsDefinition, ActionSet, or ParametersDefinition can declare maximum: 10000000000000000000, but this code strips that maximum before kube-openapi sees it, so a larger value that still fits uint64 is accepted even though it violates the schema. The overflow workaround should only bypass the kube-openapi conversion overflow while preserving the declared maximum semantics, e.g. detect the CUE type extrema separately or enforce large integer maximums manually before/after the sanitized kube-openapi validation.
stripIntegerOverflow strips Maximum >= 2^63 to prevent kube-openapi int64 overflow, but this also drops user-declared maximums (e.g., maximum: 1e19). Add validateLargeIntegerBounds to manually enforce non-CUE-extremum maximums after kube-openapi validation. CUE type extrema (2^63, 2^64) are skipped because ParseInt/ParseUint already enforce type range. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
@leon-ape Addressed your review comment in commit 5ca17b6. Problem: stripIntegerOverflow was stripping ALL large maximums, including user-declared ones like maximum: 1e19. This weakened the shared validation contract. Fix: Added validateLargeIntegerBounds that runs after kube-openapi validation to manually enforce stripped maximums. CUE type extrema (2^63 for int64, 2^64 for uint64) are skipped because ParseInt/ParseUint already enforce the type range. User-declared maximums like 1e19 are now enforced via float64 comparison (same precision as the schema declaration). New tests: TestValidateLargeIntegerBounds (unit), TestValidateDataWithSchemaUserDeclaredLargeMax (end-to-end). Both verify that values within user max pass and values above are rejected. |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #10439 +/- ##
==========================================
+ Coverage 62.04% 62.09% +0.05%
==========================================
Files 533 533
Lines 63625 63707 +82
==========================================
+ Hits 39473 39561 +88
Misses 20550 20550
+ Partials 3602 3596 -6
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
| f = float64(v) | ||
| case uint64: | ||
| f = float64(v) | ||
| default: |
There was a problem hiding this comment.
This still leaves the stripped maximum unenforced for direct ValidateDataWithSchema callers whose parsed data is not int64 or uint64. schemaValidator.Validate passes config parser output directly into this shared helper, so JSON/YAML numeric values can arrive as other numeric Go types instead of the typed map produced by ConvertStringToInterfaceBySchemaType. After stripIntegerOverflow removes Maximum from the schema, kube-openapi no longer enforces the bound, this default branch skips the manual check, and an over-limit value can pass validation. Please normalize and check all numeric representations accepted by ValidateDataWithSchema, or only strip maximums on paths where the data was first converted to the expected integer type.
There was a problem hiding this comment.
Fixed in commit ece899a.
Extracted toFloat64 helper that normalizes all numeric Go types (float64, float32, int, int32, int64, uint, uint32, uint64) before the bounds comparison.
I traced all ValidateDataWithSchema callers:
parameter_assignment.go— callsConvertStringToInterfaceBySchemaTypefirst → produces int64/uint64, already coveredcustom.go,utils.go— same pattern, ConvertStringToInterfaceBySchemaType first → safeconfig_validate.go(schemaValidator.Validate) — callsLoadConfigObjectFromContentwhich parses raw JSON/YAML/TOML → can produceint(YAML),int64(Viper/TOML),float64(JSON). This was the gap.
Note: kube-openapi itself rejects float64 for integer schemas ("must be of type integer"), so JSON-parsed float64 values are caught before reaching validateLargeIntegerBounds. The real gap was int from YAML parsers — now handled. The toFloat64 helper covers all types defensively.
Added tests:
- Unit: float64/int values against
validateLargeIntegerBoundsdirectly - End-to-end: int/int32 values through full
ValidateDataWithSchemapipeline
Address Leon11's review: config parser paths (JSON/YAML/TOML) can produce int, int32, float64 etc., not just int64/uint64. Extract toFloat64 helper to handle all numeric Go types so stripped maximums are enforced regardless of the parser's output type. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
/nopick |
Summary
ValidateDataWithSchemaboundaryAddresses leon-ape P1 (preserve uint64 range, values above MaxInt64 are accepted) and P2 (fix at shared boundary, not per-caller) review comments on #10412.
Closes #10434
Test plan
TestConvertStringToInterfaceBySchemaTypeUint64: ParseUint for CUE uint64 schemas, reject negativeTestValidateDataWithSchemaUint64: uint64 values including above MaxInt64 pass validationTestValidateDataWithSchemaInt64: int64 values with CUE-generated bounds pass validationTestStripIntegerOverflow: Maximum stripped for overflow, preserved for safe valuesTestValidateComponentParameterAssignmentsUint64: end-to-end with CUE ParametersDefinition schemaTestValidateComponentParameterAssignmentsstill passes (no regression)🤖 Generated with Claude Code