Skip to content

Fix HostBuffer.emplace overflow at block boundary#186539

Open
soulman-is-good wants to merge 1 commit into
flutter:masterfrom
soulman-is-good:fix/host-buffer-overflow-emplace-check
Open

Fix HostBuffer.emplace overflow at block boundary#186539
soulman-is-good wants to merge 1 commit into
flutter:masterfrom
soulman-is-good:fix/host-buffer-overflow-emplace-check

Conversation

@soulman-is-good
Copy link
Copy Markdown

HostBuffer._allocateEmplacement decided whether to allocate a new block based on the post-padding cursor only, ignoring the size of the data being emplaced. When the cursor landed inside the range [blockLengthInBytes - bytes.lengthInBytes, blockLengthInBytes), the check passed but the subsequent DeviceBuffer.overwrite rejected the write because it would extend past the block end, throwing:

Failed to write range (offset=..., length=...) to HostBuffer-managed
DeviceBuffer (frame=0, buffer=0, offset=...).

This was reproducible in flame_3d 3D apps once per-frame uniform traffic neared 1 MB at certain camera angles.

Include the upcoming write size in the boundary check:

if (_offsetCursor + padding + bytes.lengthInBytes > blockLengthInBytes) {

The strict > (rather than >=) is intentional: a write that exactly fills the remaining space is valid and shouldn't waste a new block.

Adds a regression test that exercises the boundary by configuring a small blockLengthInBytes and emplacing a payload that would overflow the current block under the previous check.

Fixes #186526

Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.

List which issues are fixed by this PR. You must list at least one issue. An issue is not required if the PR fixes something trivial like a typo.

If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

If this change needs to override an active code freeze, provide a comment explaining why. The code freeze workflow can be overridden by code reviewers. See pinned issues for any active code freezes with guidance.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@github-actions github-actions Bot added engine flutter/engine related. See also e: labels. flutter-gpu team-fluttergpu Owned by Flutter GPU team labels May 14, 2026
@github-project-automation github-project-automation Bot moved this to 🤔 Needs Triage in Flutter GPU May 14, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request modifies the HostBuffer allocation logic to include payload size in bounds checks, preventing out-of-bounds writes when the cursor is near the end of a block. It also introduces a regression test to verify this behavior. Review feedback identified a copy-paste error in the test assertions where the view length was incorrectly compared to the total block size instead of the payload size.

// original one, and start at offset 0 of that block.
expect(view.buffer, isNot(equals(fillView.buffer)));
expect(view.offsetInBytes, 0);
expect(view.lengthInBytes, blockLength);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

medium

The expectation for view.lengthInBytes appears to be a copy-paste error. It should be checked against overflowingSize (the size of the data emplaced), which is consistent with how fillView.lengthInBytes was checked against fillSize on line 281. Checking against blockLength would imply the view covers the entire block, which is not the behavior of emplace.

Suggested change
expect(view.lengthInBytes, blockLength);
expect(view.lengthInBytes, overflowingSize);

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I removed unrelated assertion so the test only checks related things

`HostBuffer._allocateEmplacement` decided whether to allocate a new
block based on the post-padding cursor only, ignoring the size of the
data being emplaced. When the cursor landed inside the range
`[blockLengthInBytes - bytes.lengthInBytes, blockLengthInBytes)`, the
check passed but the subsequent `DeviceBuffer.overwrite` rejected the
write because it would extend past the block end, throwing:

  Failed to write range (offset=..., length=...) to HostBuffer-managed
  DeviceBuffer (frame=0, buffer=0, offset=...).

This was reproducible in flame_3d 3D apps once per-frame uniform traffic
neared 1 MB at certain camera angles.

Include the upcoming write size in the boundary check:

    if (_offsetCursor + padding + bytes.lengthInBytes > blockLengthInBytes) {

The strict `>` (rather than `>=`) is intentional: a write that exactly
fills the remaining space is valid and shouldn't waste a new block.

Adds a regression test that exercises the boundary by configuring a
small `blockLengthInBytes` and emplacing a payload that would overflow
the current block under the previous check.

Fixes flutter#186526
@soulman-is-good soulman-is-good force-pushed the fix/host-buffer-overflow-emplace-check branch from 9b4b631 to 65b7a68 Compare May 14, 2026 18:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

engine flutter/engine related. See also e: labels. flutter-gpu team-fluttergpu Owned by Flutter GPU team

Projects

Status: 🤔 Needs Triage

Development

Successfully merging this pull request may close these issues.

HostBuffer.emplace overflows DeviceBuffer near block end (off-by-one in size check)

1 participant