Skip to content

fix(parameters): handle uint64 schema validation at shared boundary - #10439

Merged
leon-ape merged 3 commits into
mainfrom
bugfix/uint64-validation-shared-boundary
Jun 24, 2026
Merged

fix(parameters): handle uint64 schema validation at shared boundary#10439
leon-ape merged 3 commits into
mainfrom
bugfix/uint64-validation-shared-boundary

Conversation

@weicao

@weicao weicao commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Fix kube-openapi int64 overflow when validating CUE-generated uint64/int64 schemas at the shared ValidateDataWithSchema boundary
  • Detect uint64 schemas by CUE-generated bounds (Minimum >= 0, Maximum > 2^63) since CUE does not set Format
  • Strip overflowing Maximum before passing to kube-openapi; range is enforced by ParseUint/ParseInt
  • All callers (ComponentParameterAssignments, OpsDefinition, DataProtection ActionSet) are protected

Addresses 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 negative
  • TestValidateDataWithSchemaUint64: uint64 values including above MaxInt64 pass validation
  • TestValidateDataWithSchemaInt64: int64 values with CUE-generated bounds pass validation
  • TestStripIntegerOverflow: Maximum stripped for overflow, preserved for safe values
  • TestValidateComponentParameterAssignmentsUint64: end-to-end with CUE ParametersDefinition schema
  • Existing TestValidateComponentParameterAssignments still passes (no regression)

🤖 Generated with Claude Code

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>
@weicao
weicao requested review from a team, kizuna-lek and leon-ape as code owners June 23, 2026 09:08
@apecloud-bot

Copy link
Copy Markdown
Collaborator

Auto Cherry-pick Instructions

Usage:
  - /nopick: Not auto cherry-pick when PR merged.
  - /pick: release-x.x [release-x.x]: Auto cherry-pick to the specified branch when PR merged.

Example:
  - /nopick
  - /pick release-1.1

CLA Recheck Instructions

Usage:
  - /recheck-cla: Trigger a re-check of CLA status for this pull request.
Example:
  - /recheck-cla

@github-actions github-actions Bot added the size/L Denotes a PR that changes 100-499 lines. label Jun 23, 2026
}
out := schema.DeepCopy()
for k, prop := range out.Properties {
if prop.Type == "integer" && prop.Maximum != nil && *prop.Maximum >= math.Exp2(63) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@weicao

weicao commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

@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

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 63.52941% with 31 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.09%. Comparing base (4933980) to head (ece899a).

Files with missing lines Patch % Lines
pkg/common/openapiv3schema.go 65.85% 22 Missing and 6 partials ⚠️
pkg/parameters/value_transformer.go 0.00% 2 Missing and 1 partial ⚠️
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     
Flag Coverage Δ
unittests 62.09% <63.52%> (+0.05%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Comment thread pkg/common/openapiv3schema.go Outdated
f = float64(v)
case uint64:
f = float64(v)
default:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 — calls ConvertStringToInterfaceBySchemaType first → produces int64/uint64, already covered
  • custom.go, utils.go — same pattern, ConvertStringToInterfaceBySchemaType first → safe
  • config_validate.go (schemaValidator.Validate) — calls LoadConfigObjectFromContent which parses raw JSON/YAML/TOML → can produce int (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 validateLargeIntegerBounds directly
  • End-to-end: int/int32 values through full ValidateDataWithSchema pipeline

@weicao weicao added the kind/bug Something isn't working label Jun 23, 2026
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>
@weicao

weicao commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

/nopick

@apecloud-bot apecloud-bot added the nopick Not auto cherry-pick when PR merged label Jun 23, 2026
@apecloud-bot apecloud-bot added the approved PR Approved Test label Jun 24, 2026
@leon-ape
leon-ape merged commit d491444 into main Jun 24, 2026
44 of 45 checks passed
@leon-ape
leon-ape deleted the bugfix/uint64-validation-shared-boundary branch June 24, 2026 02:21
@github-actions github-actions Bot added this to the Release 1.2.0 milestone Jun 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved PR Approved Test kind/bug Something isn't working nopick Not auto cherry-pick when PR merged size/L Denotes a PR that changes 100-499 lines.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Controller should log lifecycle action dispatch (pod, action, HTTP result)

3 participants