Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
shader_library_unittests.cc
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <cstdint>
8#include <memory>
9#include <vector>
10
11#include "fml/mapping.h"
12#include "gtest/gtest.h"
14// Pulls in flatbuffers/flatbuffers.h (FlatBufferBuilder, Verifier) and the
15// generated impeller::fb::shaderbundle:: symbols.
16#include "impeller/shader_bundle/shader_bundle_flatbuffers.h"
17
18namespace flutter {
19namespace gpu {
20namespace testing {
21
22// Wraps an owning byte vector in an fml::Mapping that keeps the vector alive
23// for the lifetime of the mapping. Mirrors the helper pattern used by the
24// impeller runtime_stage / shader_archive verifier tests.
25static std::shared_ptr<fml::Mapping> CreateMappingFromVector(
26 const std::shared_ptr<std::vector<uint8_t>>& data) {
27 const uint8_t* ptr = data->data();
28 const size_t size = data->size();
29 return std::make_shared<fml::NonOwnedMapping>(ptr, size,
30 [data](auto, auto) {});
31}
32
33// Builds a structurally-valid, minimal shader bundle FlatBuffer with the
34// correct "IPSB" identifier and an empty (but present) shaders vector. This is
35// used as a positive control: the verifier added by this change must ACCEPT a
36// well-formed buffer, so that the rejection tests below prove the verifier is
37// catching genuinely corrupt input rather than rejecting everything.
38static std::shared_ptr<std::vector<uint8_t>> BuildValidEmptyBundle() {
39 flatbuffers::FlatBufferBuilder builder;
40 std::vector<flatbuffers::Offset<impeller::fb::shaderbundle::Shader>> shaders;
41 auto shaders_vec = builder.CreateVector(shaders);
42 impeller::fb::shaderbundle::ShaderBundleBuilder bundle_builder(builder);
43 bundle_builder.add_format_version(static_cast<uint32_t>(
44 impeller::fb::shaderbundle::ShaderBundleFormatVersion::kVersion));
45 bundle_builder.add_shaders(shaders_vec);
46 auto bundle = bundle_builder.Finish();
47 // Finish with the "IPSB" file identifier (mirrors the runtime_stage test's
48 // builder.Finish(stages, fb::RuntimeStagesIdentifier()) idiom).
49 builder.Finish(bundle, impeller::fb::shaderbundle::ShaderBundleIdentifier());
50 return std::make_shared<std::vector<uint8_t>>(
51 builder.GetBufferPointer(),
52 builder.GetBufferPointer() + builder.GetSize());
53}
54
55// A corrupt buffer with a valid "IPSB" file identifier at bytes 4-7 but a root
56// table offset that points beyond the buffer. This passes the identifier check
57// (ShaderBundleBufferHasIdentifier) but must fail FlatBuffer structural
58// verification (VerifyShaderBundleBuffer). Mirrors the impeller
59// RejectsCorruptBufferWithValidIdentifier tests for runtime_stage / shader
60// archive.
61static std::shared_ptr<std::vector<uint8_t>> BuildCorruptBundle() {
62 auto data = std::make_shared<std::vector<uint8_t>>(32, 0);
63 // "IPSB" file identifier at bytes 4-7.
64 (*data)[4] = 'I';
65 (*data)[5] = 'P';
66 (*data)[6] = 'S';
67 (*data)[7] = 'B';
68 // Root offset (little-endian uint32 at offset 0) pointing out of bounds.
69 (*data)[0] = 0xFF;
70 (*data)[1] = 0xFF;
71 return data;
72}
73
74// Sanity check on the test fixtures themselves: the corrupt buffer carries the
75// expected identifier (so it reaches the new verification) while failing
76// structural verification, and the valid buffer passes both.
77TEST(FlutterGpuShaderLibraryTest, VerifierAcceptsValidBundleRejectsCorrupt) {
78 auto valid = BuildValidEmptyBundle();
79 EXPECT_TRUE(impeller::fb::shaderbundle::ShaderBundleBufferHasIdentifier(
80 valid->data()));
81 {
82 flatbuffers::Verifier verifier(valid->data(), valid->size());
83 EXPECT_TRUE(impeller::fb::shaderbundle::VerifyShaderBundleBuffer(verifier));
84 }
85
86 auto corrupt = BuildCorruptBundle();
87 EXPECT_TRUE(impeller::fb::shaderbundle::ShaderBundleBufferHasIdentifier(
88 corrupt->data()));
89 {
90 flatbuffers::Verifier verifier(corrupt->data(), corrupt->size());
91 EXPECT_FALSE(
92 impeller::fb::shaderbundle::VerifyShaderBundleBuffer(verifier));
93 }
94}
95
96// Core regression: a buffer with a valid "IPSB" identifier but corrupt internal
97// offsets must be rejected (null library) rather than read out of bounds. Prior
98// to the structural verification this exercised GetShaderBundle() on unverified
99// data.
100TEST(FlutterGpuShaderLibraryTest,
101 MakeFromFlatbufferRejectsCorruptBufferWithValidIdentifier) {
103 auto library =
105 std::move(mapping), "test_bundle");
106 EXPECT_FALSE(library);
107}
108
109// A truncated buffer (shorter than a FlatBuffer header) with the identifier
110// bytes must also be rejected without reading out of bounds.
111TEST(FlutterGpuShaderLibraryTest, MakeFromFlatbufferRejectsTruncatedBuffer) {
112 // 8 bytes: just enough to hold a (bogus) root offset + "IPSB" identifier.
113 auto data = std::make_shared<std::vector<uint8_t>>(8, 0);
114 (*data)[4] = 'I';
115 (*data)[5] = 'P';
116 (*data)[6] = 'S';
117 (*data)[7] = 'B';
118 // Root offset points past the 8-byte buffer.
119 (*data)[0] = 0x10;
122 "test_bundle");
123 EXPECT_FALSE(library);
124}
125
126// A buffer without the "IPSB" identifier is rejected at the identifier check
127// (pre-existing behavior, guarded here against regression).
128TEST(FlutterGpuShaderLibraryTest, MakeFromFlatbufferRejectsMissingIdentifier) {
129 auto data = std::make_shared<std::vector<uint8_t>>(32, 0);
130 // No identifier bytes set.
133 "test_bundle");
134 EXPECT_FALSE(library);
135}
136
137// A null payload must be handled gracefully.
138TEST(FlutterGpuShaderLibraryTest, MakeFromFlatbufferRejectsNullPayload) {
140 impeller::Context::BackendType::kMetal, nullptr, "test_bundle");
141 EXPECT_FALSE(library);
142}
143
144// A structurally-valid bundle that simply contains no shaders parses to an
145// empty shader map, which MakeFromFlatbuffer reports as a null library. This
146// confirms the verifier does NOT reject a well-formed buffer (the failure in
147// the corrupt case above comes from structural verification, not from the
148// buffer being non-empty).
149TEST(FlutterGpuShaderLibraryTest,
150 MakeFromFlatbufferValidEmptyBundleIsNotRejectedByVerifier) {
151 auto valid = BuildValidEmptyBundle();
152 // The verifier accepts it (asserted directly here so this test stands alone).
153 flatbuffers::Verifier verifier(valid->data(), valid->size());
154 ASSERT_TRUE(impeller::fb::shaderbundle::VerifyShaderBundleBuffer(verifier));
155
156 // Driven through the public entry, an empty bundle yields a null library
157 // because there are no shaders to register (empty ShaderMap), NOT because the
158 // verifier rejected it.
161 "test_bundle");
162 EXPECT_FALSE(library);
163}
164
165} // namespace testing
166} // namespace gpu
167} // namespace flutter
static fml::RefPtr< ShaderLibrary > MakeFromFlatbuffer(impeller::Context::BackendType backend_type, std::shared_ptr< fml::Mapping > payload, std::string library_id="")
static std::shared_ptr< std::vector< uint8_t > > BuildValidEmptyBundle()
static std::shared_ptr< std::vector< uint8_t > > BuildCorruptBundle()
TEST(FlutterGpuShaderLibraryTest, VerifierAcceptsValidBundleRejectsCorrupt)
static std::shared_ptr< fml::Mapping > CreateMappingFromVector(const std::shared_ptr< std::vector< uint8_t > > &data)
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switch_defs.h:36