Skip to content

fix(packer): use Uint64() to prevent silent overflow on GasAllocated#21412

Open
Aboudjem wants to merge 2 commits intosmartcontractkit:developfrom
Aboudjem:fix/packer-gas-allocated-overflow
Open

fix(packer): use Uint64() to prevent silent overflow on GasAllocated#21412
Aboudjem wants to merge 2 commits intosmartcontractkit:developfrom
Aboudjem:fix/packer-gas-allocated-overflow

Conversation

@Aboudjem
Copy link

@Aboudjem Aboudjem commented Mar 5, 2026

Summary

UnpackCheckResult in packer.go uses big.Int.Int64() to populate the uint64 field GasAllocated. If the on-chain value exceeds math.MaxInt64 (2^63-1), Int64() silently truncates and returns a negative value, which then wraps to a large positive uint64. This could cause upkeep gas budgets to be wildly incorrect.

The fix extracts the *big.Int, checks IsUint64(), and returns an error if the value overflows. Otherwise it uses .Uint64() for a safe conversion.

Changes

  • core/services/ocr2/plugins/ocr2keeper/evmregistry/v21/encoding/packer.go - 7 lines added, 1 removed

Test plan

  • go build passes on the target package
  • Diff limited to single target file
  • Existing unit tests pass (CI will verify)

Copilot AI review requested due to automatic review settings March 5, 2026 10:57
@Aboudjem Aboudjem requested a review from a team as a code owner March 5, 2026 10:57
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a silent integer overflow bug in UnpackCheckResult in the OCR2 Keeper V21 ABI packer. Previously, the GasAllocated field (a uint64) was populated via big.Int.Int64(), which silently truncates values above math.MaxInt64 (2^63-1) and returns a negative value that wraps to a large positive uint64. The fix extracts the *big.Int, validates it via IsUint64(), and returns an error with a proper ineligible check result if it overflows.

Changes:

  • Extracts GasAllocated as a *big.Int before conversion, validates range with IsUint64(), and switches from Int64() to Uint64() for the safe cast.

Comment on lines +49 to +52
if !gasAllocatedBig.IsUint64() {
return GetIneligibleCheckResultWithoutPerformData(payload, UpkeepFailureReasonNone, PackUnpackDecodeFailed, false),
fmt.Errorf("upkeepId %s GasAllocated value %s overflows uint64", payload.UpkeepID.String(), gasAllocatedBig.String())
}
Copy link

Copilot AI Mar 5, 2026

Choose a reason for hiding this comment

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

The new overflow check path lacks a unit test. The existing test file (packer_test.go) has dedicated tests for the decode failed and unpack failed error paths in UnpackCheckResult, but there is no test case covering the new GasAllocated overflows uint64 error path. A test case should be added with a raw hex payload whose out[4] encodes a value larger than math.MaxUint64 (e.g., a 256-bit integer with bits set above the 64-bit boundary), verifying that the error is returned and the result has PipelineExecutionState set to PackUnpackDecodeFailed.

Copilot uses AI. Check for mistakes.
Copy link
Author

Choose a reason for hiding this comment

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

The test is already there - see the "gas allocated overflow" case in packer_test.go (added in commit 875fbcb). It encodes GasAllocated as 2^64 (math.MaxUint64+1) and asserts the overflow error.

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.

2 participants