Skip to content

fix: avoid int32 overflow when maxTrafficWeight is large - #4923

Open
semx wants to merge 1 commit into
argoproj:masterfrom
semx:fix/max-traffic-weight-overflow
Open

fix: avoid int32 overflow when maxTrafficWeight is large#4923
semx wants to merge 1 commit into
argoproj:masterfrom
semx:fix/max-traffic-weight-overflow

Conversation

@semx

@semx semx commented Jul 27, 2026

Copy link
Copy Markdown

Fixes canary replica counts being computed from an overflowed int32 product when maxTrafficWeight is large.

The problem

Several places multiply a replica count by a traffic weight while both are still int32, and only widen the result afterwards:

ceilWeightedCanaryCount := int32(math.Ceil(float64(specReplicas*desiredWeight) / float64(maxWeight)))

maxTrafficWeight has no upper bound (the CRD only says format: int32), and the repo's own tests use 100000000. At that scale the product exceeds math.MaxInt32 for quite ordinary replica counts, and the arithmetic wraps.

approximateWeightedCanaryStableReplicaCounts with maxWeight=100000000, maxSurge=0:

replicas weight canary (before) canary (expected)
43 50% -21 22
100 50% 8 50
43 100% 1 43

A negative canary count at 50%, and a single canary replica when the rollout is fully shifted to canary.

checkReplicasAvailable is affected the same way: the overflowed product goes negative, so availableReplicas < desiredReplicas is never true and it reports that there are enough replicas. With 43 replicas at 50% weight and zero of them available it returns true, which lets traffic shift to pods that are not ready.

The threshold is replicas * weight > MaxInt32, so with maxTrafficWeight=100000000 it starts at about 22 replicas.

The fix

Widen the operands before multiplying. trafficWeightToReplicas in the same file already does exactly this:

func trafficWeightToReplicas(replicas, weight, maxWeight int32) int32 {
	return int32(math.Ceil(float64(weight) * float64(replicas) / float64(maxWeight)))
}

The same shape is applied to approximateWeightedCanaryStableReplicaCounts, weightDelta, checkReplicasAvailable, the dynamic-stable-scale weight in trafficrouting.go, and the actual-weight display in rollout_info.go. Behaviour for the default maxTrafficWeight=100 is unchanged — the existing table cases all still pass.

Tests

Added cases to the existing tables. Both fail on master and pass with this change:

  • TestApproximateWeightedNewStableReplicaCountsexpected: 22, actual: -21 and expected: 50, actual: 8
  • TestCheckReplicasAvailableWithCustomMaxTrafficWeight — 43 replicas, 0 available, 50% weight must not report available

replicas and weights were multiplied as int32 before being widened, so
a large maxTrafficWeight overflowed the product and the canary counts
came out wrong. With maxTrafficWeight=100000000, a 43 replica rollout at
50% weight produced -21 canary replicas, and at 100% weight it produced
1 canary replica instead of 43.

Widen the operands before multiplying, the way trafficWeightToReplicas
already does.

Signed-off-by: semx <7532921+semx@users.noreply.github.com>
@semx
semx requested a review from a team as a code owner July 27, 2026 08:23
@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

Published E2E Test Results

  4 files    4 suites   3h 52m 55s ⏱️
123 tests 114 ✅  7 💤 2 ❌
496 runs  464 ✅ 28 💤 4 ❌

For more details on these failures, see this check.

Results for commit c3cd007.

@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.07%. Comparing base (d1dd467) to head (c3cd007).

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4923      +/-   ##
==========================================
- Coverage   85.12%   85.07%   -0.06%     
==========================================
  Files         166      166              
  Lines       19238    19239       +1     
==========================================
- Hits        16376    16367       -9     
- Misses       2019     2024       +5     
- Partials      843      848       +5     
Flag Coverage Δ
e2e 52.42% <83.33%> (-0.10%) ⬇️
unit-tests 81.55% <100.00%> (+<0.01%) ⬆️

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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions

Copy link
Copy Markdown
Contributor

Published Unit Test Results

2 584 tests   2 584 ✅  3m 24s ⏱️
  130 suites      0 💤
    1 files        0 ❌

Results for commit c3cd007.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant