Skip to content

Verify shader bundle FlatBuffer before access in flutter_gpu ShaderLibrary#188252

Merged
auto-submit[bot] merged 6 commits into
flutter:masterfrom
adilburaksen:fix-shaderbundle-verifier
Jun 28, 2026
Merged

Verify shader bundle FlatBuffer before access in flutter_gpu ShaderLibrary#188252
auto-submit[bot] merged 6 commits into
flutter:masterfrom
adilburaksen:fix-shaderbundle-verifier

Conversation

@adilburaksen

Copy link
Copy Markdown
Contributor

Description

ParseShaderBundle in engine/src/flutter/lib/gpu/shader_library.cc checks the
"IPSB" file identifier and then immediately calls GetShaderBundle() and reads
fields (format_version(), the shaders vector, names, mappings) without first
running a flatbuffers::Verifier
. A buffer with a valid identifier but corrupt
internal offsets is therefore read out of bounds.

This is the same structural-verification gap that was recently fixed for the two
sibling loaders in #187878:

  • impeller/runtime_stage/runtime_stage.cc (VerifyRuntimeStagesBuffer)
  • impeller/shader_archive/shader_archive.cc (VerifyShaderArchiveBuffer)

The flutter_gpu shader-bundle loader (IPSB), reachable via
ShaderLibrary.fromAsset / MakeFromFlatbuffer, was not covered by that change.

Change

Add a VerifyShaderBundleBuffer() check after the identifier check and before
GetShaderBundle(), mirroring the sibling loaders. The generated
shader_bundle_flatbuffers.h (already included) provides the verifier; no new
include is required. On verification failure the loader returns an empty shader
map, consistent with the function's existing early-return behavior.

I'm happy to add a unit test mirroring RejectsCorruptBufferWithValidIdentifier
from #187878 if a maintainer prefers it wired in.

…brary

ParseShaderBundle in lib/gpu/shader_library.cc checks the "IPSB" file
identifier and then calls GetShaderBundle() and reads fields from the buffer
without first running a flatbuffers::Verifier. A buffer with a valid identifier
but corrupt internal offsets is therefore read out of bounds.

Add a VerifyShaderBundleBuffer() check after the identifier check and before
GetShaderBundle(), mirroring the verification recently added for the runtime
stage and shader archive loaders.
@flutter-dashboard

Copy link
Copy Markdown

It looks like this pull request may not have tests. Please make sure to add tests or get an explicit test exemption before merging.

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. If you believe this PR qualifies for a test exemption, contact "@test-exemption-reviewer" in the #hackers channel in Discord (don't just cc them here, they won't see it!). The test exemption team is a small volunteer group, so all reviewers should feel empowered to ask for tests, without delegating that responsibility entirely to the test exemption group.

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

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

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.

Code Review

This pull request introduces structural verification of the FlatBuffer in ParseShaderBundle before accessing its fields to prevent potential out-of-bounds reads. The review feedback recommends removing a redundant reinterpret_cast on payload->GetMapping() to simplify the verifier initialization.

Comment on lines +189 to +191
flatbuffers::Verifier verifier(
reinterpret_cast<const uint8_t*>(payload->GetMapping()),
payload->GetSize());

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

Since fml::Mapping::GetMapping() already returns const uint8_t*, the reinterpret_cast is redundant. Removing it simplifies the code and improves readability.

  flatbuffers::Verifier verifier(payload->GetMapping(), payload->GetSize());
References
  1. Avoid redundant casts to keep the code clean and readable, adhering to general C++ best practices and the Google C++ Style Guide. (link)

@gaaclarke gaaclarke requested a review from bdero June 22, 2026 18:06
@gaaclarke

Copy link
Copy Markdown
Member

@bdero we just landed a similar PR for the flat buffers for shaders in impeller. This seems like something we'd want to do. I believe we had tests for our PR though. Can you give this a look?

@adilburaksen I don't have the PR off hand but can you look at the one that added this verification for impeller and see how to potentially add some tests?

Adds shader_library_unittests.cc covering ShaderLibrary::MakeFromFlatbuffer:
a corrupt or truncated shader bundle with a valid IPSB identifier, a buffer
without the identifier, and a null payload are all rejected (null library),
while a structurally valid bundle passes verification. Mirrors the corrupt
buffer tests for the impeller runtime stage and shader archive loaders.
@adilburaksen

Copy link
Copy Markdown
Contributor Author

Thanks @gaaclarke! I added unit tests in lib/gpu/shader_library_unittests.cc that mirror the corrupt-buffer tests in the impeller runtime stage and shader archive loaders. They drive ShaderLibrary::MakeFromFlatbuffer and check that a corrupt buffer with a valid IPSB identifier, a truncated buffer, a buffer without the identifier, and a null payload are all rejected (null library), plus a positive control that a structurally valid bundle passes VerifyShaderBundleBuffer. I also added the shader_bundle_flatbuffers dep to the gpu_unittests target for the flatbuffer symbols. PTAL.

@gaaclarke gaaclarke added the CICD Run CI/CD label Jun 22, 2026
@gaaclarke gaaclarke requested a review from andywolff June 22, 2026 19:32
bdero
bdero previously approved these changes Jun 22, 2026

@bdero bdero left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM

@andywolff andywolff left a comment

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.

LGTM except for one small change requested to fix compilation failure

auto library = ShaderLibrary::MakeFromFlatbuffer(
impeller::Context::BackendType::kMetal, std::move(mapping),
"test_bundle");
EXPECT_EQ(library, nullptr);

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.

When I tried running these tests locally on my mac, compilation of gpu_unittests with et build failed with error:

error: invalid operands to binary expression ('const fml::RefPtrflutter::gpu::ShaderLibrary' and 'const std::nullptr_t')

This occurs because fml::RefPtr does not define operator== with std::nullptr_t. The tests compile and pass for me if we use EXPECT_FALSE(library) instead of EXPECT_EQ(library, nullptr)

fml::RefPtr does not define operator== with std::nullptr_t, so
EXPECT_EQ(library, nullptr) fails to compile. Use EXPECT_FALSE(library).
@adilburaksen

Copy link
Copy Markdown
Contributor Author

Thanks @andywolff! Switched all five EXPECT_EQ(library, nullptr) to EXPECT_FALSE(library) since fml::RefPtr has no operator== with nullptr_t. Pushed.

andywolff
andywolff previously approved these changes Jun 22, 2026
@gaaclarke gaaclarke added the CICD Run CI/CD label Jun 22, 2026
gaaclarke
gaaclarke previously approved these changes Jun 22, 2026
@gaaclarke gaaclarke added the autosubmit Merge PR when tree becomes green via auto submit App label Jun 22, 2026
@auto-submit auto-submit Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jun 23, 2026
@auto-submit

auto-submit Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

autosubmit label was removed for flutter/flutter/188252, because - The status or check suite Linux linux_unopt has failed. Please fix the issues identified (or deflake) before re-applying this label.

Resolves the clang-tidy performance-unnecessary-value-param error and the
engine clang-format check on shader_library_unittests.cc.
@adilburaksen adilburaksen dismissed stale reviews from gaaclarke and andywolff via a958e01 June 23, 2026 00:32
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 23, 2026
@bdero

bdero commented Jun 26, 2026

Copy link
Copy Markdown
Member

Ah, it's best to re-request review after previous reviews go stale due to a push. Otherwise the PR won't end up in people's review queues and may get lost in the ocean of activity going on around Flutter.

@flutter-dashboard flutter-dashboard Bot removed the CICD Run CI/CD label Jun 28, 2026
@bdero bdero added CICD Run CI/CD autosubmit Merge PR when tree becomes green via auto submit App labels Jun 28, 2026
@auto-submit auto-submit Bot added this pull request to the merge queue Jun 28, 2026
Merged via the queue into flutter:master with commit 744a6e3 Jun 28, 2026
210 checks passed
@github-project-automation github-project-automation Bot moved this from ⚙️ In Progress to ✅ Done in Flutter GPU Jun 28, 2026
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jun 28, 2026
This was referenced Jun 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

4 participants