Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
image_generator_apng_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 <cstring>
9#include <vector>
10
13#include "third_party/skia/include/core/SkData.h"
14
15namespace flutter {
16namespace testing {
17
18namespace {
19
20// Writes a big-endian uint32_t to a buffer.
21void WriteBE32(std::vector<uint8_t>& buf, uint32_t val) {
22 buf.push_back((val >> 24) & 0xFF);
23 buf.push_back((val >> 16) & 0xFF);
24 buf.push_back((val >> 8) & 0xFF);
25 buf.push_back(val & 0xFF);
26}
27
28// Writes a big-endian uint16_t to a buffer.
29void WriteBE16(std::vector<uint8_t>& buf, uint16_t val) {
30 buf.push_back((val >> 8) & 0xFF);
31 buf.push_back(val & 0xFF);
32}
33
34// Appends a PNG chunk (length + type + data + CRC) to the buffer.
35void AppendChunk(std::vector<uint8_t>& buf,
36 const char type[4],
37 const std::vector<uint8_t>& data) {
38 FML_CHECK(data.size() <= std::numeric_limits<uint32_t>::max());
39 WriteBE32(buf, static_cast<uint32_t>(data.size()));
40 size_t type_start = buf.size();
41 buf.insert(buf.end(), type, type + 4);
42 buf.insert(buf.end(), data.begin(), data.end());
43 uint32_t crc = APNGImageGenerator::ComputeCrc32(buf.data() + type_start,
44 4 + data.size());
45 WriteBE32(buf, crc);
46}
47
48// Builds a minimal valid APNG with a malicious fdAT chunk whose
49// data_length is less than 4, which would trigger an integer underflow
50// in DemuxNextImage() without the bounds check fix.
51std::vector<uint8_t> BuildMaliciousApng(uint32_t fdat_data_length) {
52 std::vector<uint8_t> apng(APNGImageGenerator::kPngSignature.begin(),
54
55 // IHDR: 1x1 RGBA, 8-bit
56 {
57 std::vector<uint8_t> ihdr;
58 WriteBE32(ihdr, 1); // width
59 WriteBE32(ihdr, 1); // height
60 ihdr.push_back(8); // bit depth
61 ihdr.push_back(6); // color type (RGBA)
62 ihdr.push_back(0); // compression
63 ihdr.push_back(0); // filter
64 ihdr.push_back(0); // interlace
65 AppendChunk(apng, "IHDR", ihdr);
66 }
67
68 // acTL: 1 frame, loop forever
69 {
70 std::vector<uint8_t> actl;
71 WriteBE32(actl, 1); // num_frames
72 WriteBE32(actl, 0); // num_plays (0 = infinite)
73 AppendChunk(apng, "acTL", actl);
74 }
75
76 // fcTL for frame 0
77 {
78 std::vector<uint8_t> fctl;
79 WriteBE32(fctl, 0); // sequence_number
80 WriteBE32(fctl, 1); // width
81 WriteBE32(fctl, 1); // height
82 WriteBE32(fctl, 0); // x_offset
83 WriteBE32(fctl, 0); // y_offset
84 WriteBE16(fctl, 1); // delay_num
85 WriteBE16(fctl, 10); // delay_den
86 fctl.push_back(0); // dispose_op
87 fctl.push_back(0); // blend_op
88 AppendChunk(apng, "fcTL", fctl);
89 }
90
91 // Malicious fdAT for frame 0: data_length < 4
92 // An fdAT chunk must have at least 4 bytes (sequence number).
93 // With data_length < 4, the subtraction in DemuxNextImage() underflows.
94 AppendChunk(apng, "fdAT", std::vector<uint8_t>(fdat_data_length, 0));
95
96 // IEND
97 AppendChunk(apng, "IEND", {});
98
99 return apng;
100}
101
102} // namespace
103
104// Verify that the APNG decoder can handle fdAT chunks whose length is shorter
105// than the required 4-byte sequence number.
106TEST(APNGImageGeneratorTest, FdATWithShortDataLengthDoesNotCrash) {
107 ImageGeneratorRegistry registry;
108
109 auto make_generator = [](uint32_t fdat_length) -> auto {
110 auto apng_bytes = BuildMaliciousApng(fdat_length);
111 auto data = SkData::MakeWithCopy(apng_bytes.data(), apng_bytes.size());
113 };
114
115 // The decoder should reject fdAT chunks that are less than 4 bytes long.
116 EXPECT_EQ(make_generator(0), nullptr);
117 EXPECT_EQ(make_generator(2), nullptr);
118
119 // Creating the generator should succeed if the fdAT has sufficient length.
120 EXPECT_NE(make_generator(4), nullptr);
121}
122
123} // namespace testing
124} // namespace flutter
static uint32_t ComputeCrc32(const uint8_t *data, size_t length)
Computes the CRC of the data in a PNG chunk.
static constexpr std::array< uint8_t, 8 > kPngSignature
Signature at the start of a PNG file.
static std::unique_ptr< ImageGenerator > MakeFromData(sk_sp< SkData > data)
Keeps a priority-ordered registry of image generator builders to be used when decoding images....
#define FML_CHECK(condition)
Definition logging.h:104
TEST(NativeAssetsManagerTest, NoAvailableAssets)
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
impeller::ShaderType type
const size_t end