Skip to content

[Flow EVM] Fix padding logic on EncodeBytes for data with multiple chunks#8425

Open
m-Peter wants to merge 1 commit intomasterfrom
mpeter/fix-encode-bytes-padding
Open

[Flow EVM] Fix padding logic on EncodeBytes for data with multiple chunks#8425
m-Peter wants to merge 1 commit intomasterfrom
mpeter/fix-encode-bytes-padding

Conversation

@m-Peter
Copy link
Collaborator

@m-Peter m-Peter commented Feb 19, 2026

  • Adds a check to ensure the given buffer has the necessary size to fit the encoded data
  • Fixes the padded size calculation, by counting the total number of 32-byte chunks

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved buffer validation to prevent encoding errors during data processing.
  • Tests

    • Added comprehensive test coverage for buffer size validation and multi-chunk data encoding scenarios.

@m-Peter m-Peter self-assigned this Feb 19, 2026
@m-Peter m-Peter requested a review from a team as a code owner February 19, 2026 15:40
@github-actions
Copy link
Contributor

Dependency Review

✅ No vulnerabilities or license issues or OpenSSF Scorecard issues found.

Scanned Files

None

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 19, 2026

📝 Walkthrough

Walkthrough

Modified ABI encoding logic to add buffer size validation and refactored padding calculation for multi-chunk data encoding. The EncodeBytes function now validates buffer capacity upfront and computes padded size using a chunks-based approach. Corresponding test cases verify buffer underflow errors and correct multi-chunk encoding output.

Changes

Cohort / File(s) Summary
ABI Buffer Validation & Encoding
fvm/evm/precompiles/abi.go, fvm/evm/precompiles/abi_test.go
Added upfront buffer size validation in EncodeBytes using SizeNeededForBytesEncoding(). Reworked padding calculation to use chunks-based approach (chunks = dataSize / FixedSizeUnitDataReadSize with remainder handling). Updated buffer boundary checks and added test cases for buffer underflow errors and multi-chunk encoding verification.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

Bugfix

Suggested reviewers

  • zhangchiqing
  • fxamacker
  • janezpodhostnik

Poem

🐰 Hops with glee, chunks aligned,
Buffers validated, padding refined,
No more overflow, no more fuss,
Encoding multiples—encoded with trust!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: fixing padding logic in EncodeBytes to handle data spanning multiple chunks, which matches the core functionality improvements in the PR.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch mpeter/fix-encode-bytes-padding

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov-commenter
Copy link

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
fvm/evm/precompiles/abi.go (1)

209-218: SizeNeededForBytesEncoding still uses paddedSize where it means chunk count — same naming pattern as the original bug.

The fix in EncodeBytes renames the intermediate variable to chunks for clarity, but SizeNeededForBytesEncoding still uses paddedSize to hold the chunk count before multiplying by FixedSizeUnitDataReadSize. The result is correct, but the inconsistency between the two functions could confuse future readers.

♻️ Suggested rename for consistency
 func SizeNeededForBytesEncoding(data []byte) int {
 	if len(data) == 0 {
 		return EncodedUint64Size + EncodedUint64Size + FixedSizeUnitDataReadSize
 	}
-	paddedSize := (len(data) / FixedSizeUnitDataReadSize)
+	chunks := (len(data) / FixedSizeUnitDataReadSize)
 	if len(data)%FixedSizeUnitDataReadSize != 0 {
-		paddedSize += 1
+		chunks += 1
 	}
-	return EncodedUint64Size + EncodedUint64Size + paddedSize*FixedSizeUnitDataReadSize
+	return EncodedUint64Size + EncodedUint64Size + chunks*FixedSizeUnitDataReadSize
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@fvm/evm/precompiles/abi.go` around lines 209 - 218,
SizeNeededForBytesEncoding uses the variable name paddedSize to represent the
number of FixedSizeUnitDataReadSize chunks (same concept as in EncodeBytes),
which is inconsistent and confusing; rename paddedSize to chunks in
SizeNeededForBytesEncoding and update its calculation and use (the return
expression that multiplies by FixedSizeUnitDataReadSize) to match EncodeBytes'
naming for clarity and maintainability while keeping the existing logic intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@fvm/evm/precompiles/abi.go`:
- Around line 209-218: SizeNeededForBytesEncoding uses the variable name
paddedSize to represent the number of FixedSizeUnitDataReadSize chunks (same
concept as in EncodeBytes), which is inconsistent and confusing; rename
paddedSize to chunks in SizeNeededForBytesEncoding and update its calculation
and use (the return expression that multiplies by FixedSizeUnitDataReadSize) to
match EncodeBytes' naming for clarity and maintainability while keeping the
existing logic intact.

Copy link
Member

@fxamacker fxamacker left a comment

Choose a reason for hiding this comment

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

Nice! I left some comments and suggestions.

Comment on lines 211 to 213
if len(data) == 0 {
return EncodedUint64Size + EncodedUint64Size + FixedSizeUnitDataReadSize
}
Copy link
Member

Choose a reason for hiding this comment

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

This PR doesn't modify SizeNeededForBytesEncoding function.

Unless I missed something, it looks like empty data should be encoded to 64 bytes (instead of 96 bytes).

encoded empty data = encoded offset (32 bytes) +
    encoded data length (32 bytes) +
    data (0 bytes because data is empty and there is no padding)

Comment on lines +234 to +238
chunks := (dataSize / FixedSizeUnitDataReadSize)
if dataSize%FixedSizeUnitDataReadSize != 0 {
paddedSize += FixedSizeUnitDataReadSize
chunks += 1
}
paddedSize := chunks * FixedSizeUnitDataReadSize
Copy link
Member

Choose a reason for hiding this comment

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

Maybe extract computation of paddedSize into its own function.

SizeNeededForBytesEncoding() also has logic to compute padded size. So we can reuse the extracted function in both SizeNeededForBytesEncoding() and EncodeBytes().

Comment on lines 239 to 241
if len(buffer) < payloadIndex+EncodedUint64Size+paddedSize {
return ErrBufferTooSmall
}
Copy link
Member

Choose a reason for hiding this comment

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

This check can be removed since we check for buffer size against encoded data at the beginning of the function.

Comment on lines +224 to +226
if len(buffer) < SizeNeededForBytesEncoding(data) {
return ErrBufferTooSmall
}
Copy link
Member

Choose a reason for hiding this comment

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

Maybe include headerIndex here in case headerIndex isn't 0.

Suggested change
if len(buffer) < SizeNeededForBytesEncoding(data) {
return ErrBufferTooSmall
}
if len(buffer) < headerIndex + SizeNeededForBytesEncoding(data) {
return ErrBufferTooSmall
}

Comment on lines 228 to 230
if len(buffer) < headerIndex+EncodedUint64Size {
return ErrBufferTooSmall
}
Copy link
Member

Choose a reason for hiding this comment

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

I think this check can be removed because it is redundant with previous check len(buffer) < headerIndex + SizeNeededForBytesEncoding(data).

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants