-
Notifications
You must be signed in to change notification settings - Fork 209
/
avifsize0test.cc
130 lines (112 loc) · 4.55 KB
/
avifsize0test.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright 2024 Google LLC
// SPDX-License-Identifier: BSD-2-Clause
#include <algorithm>
#include <cstring>
#include <iostream>
#include <string>
#include "avif/avif.h"
#include "aviftest_helpers.h"
#include "gtest/gtest.h"
namespace avif {
namespace {
// Used to pass the data folder path to the GoogleTest suites.
const char* data_path = nullptr;
//------------------------------------------------------------------------------
TEST(AvifDecodeTest, SingleWhitePixel) {
const char* file_name = "white_1x1.avif";
DecoderPtr decoder(avifDecoderCreate());
ASSERT_NE(decoder, nullptr);
ASSERT_EQ(avifDecoderSetIOFile(decoder.get(),
(std::string(data_path) + file_name).c_str()),
AVIF_RESULT_OK);
ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK);
if (testutil::Av1DecoderAvailable()) {
EXPECT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK);
}
}
TEST(AvifDecodeTest, MdatSize0) {
testutil::AvifRwData avif =
testutil::ReadFile(std::string(data_path) + "white_1x1.avif");
// Edit the file to simulate an 'mdat' box with size 0 (meaning ending at EOF)
const uint8_t* kMdat = reinterpret_cast<const uint8_t*>("mdat");
uint8_t* mdat_position =
std::search(avif.data, avif.data + avif.size, kMdat, kMdat + 4);
ASSERT_NE(mdat_position, avif.data + avif.size);
mdat_position[-1] = '\0';
DecoderPtr decoder(avifDecoderCreate());
ASSERT_NE(decoder, nullptr);
ASSERT_EQ(avifDecoderSetIOMemory(decoder.get(), avif.data, avif.size),
AVIF_RESULT_OK);
ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK);
if (testutil::Av1DecoderAvailable()) {
EXPECT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK);
}
}
TEST(AvifDecodeTest, MetaSize0) {
testutil::AvifRwData avif =
testutil::ReadFile(std::string(data_path) + "white_1x1.avif");
// Edit the file to simulate a 'meta' box with size 0 (invalid).
const uint8_t* kMeta = reinterpret_cast<const uint8_t*>("meta");
uint8_t* meta_position =
std::search(avif.data, avif.data + avif.size, kMeta, kMeta + 4);
ASSERT_NE(meta_position, avif.data + avif.size);
meta_position[-1] = '\0';
DecoderPtr decoder(avifDecoderCreate());
ASSERT_NE(decoder, nullptr);
ASSERT_EQ(avifDecoderSetIOMemory(decoder.get(), avif.data, avif.size),
AVIF_RESULT_OK);
// This should fail because the meta box contains the mdat box.
// However, the section 8.11.3.1 of ISO/IEC 14496-12 does not explicitly
// require the coded image item extents to be read from the MediaDataBox if
// the construction_method is 0.
// Maybe another section or specification enforces that.
ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_OK);
if (testutil::Av1DecoderAvailable()) {
EXPECT_EQ(avifDecoderNextImage(decoder.get()), AVIF_RESULT_OK);
}
}
TEST(AvifDecodeTest, FtypSize0) {
testutil::AvifRwData avif =
testutil::ReadFile(std::string(data_path) + "white_1x1.avif");
// Edit the file to simulate a 'ftyp' box with size 0 (invalid).
avif.data[3] = '\0';
DecoderPtr decoder(avifDecoderCreate());
ASSERT_NE(decoder, nullptr);
ASSERT_EQ(avifDecoderSetIOMemory(decoder.get(), avif.data, avif.size),
AVIF_RESULT_OK);
ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_BMFF_PARSE_FAILED);
}
TEST(AvifDecodeTest, UnknownTopLevelBoxSize0) {
testutil::AvifRwData avif =
testutil::ReadFile(std::string(data_path) + "white_1x1.avif");
// Edit the file to insert an unknown top level box with size 0 after ftyp
// (invalid).
testutil::AvifRwData avif_edited;
ASSERT_EQ(avifRWDataRealloc(&avif_edited, avif.size + 8), AVIF_RESULT_OK);
// Copy the ftyp box.
std::memcpy(avif_edited.data, avif.data, 32);
// Set 8 bytes to 0 (box type and size all 0s).
std::memset(avif_edited.data + 32, 0, 8);
// Copy the other boxes.
std::memcpy(avif_edited.data + 40, avif.data + 32, avif.size - 32);
DecoderPtr decoder(avifDecoderCreate());
ASSERT_NE(decoder, nullptr);
ASSERT_EQ(
avifDecoderSetIOMemory(decoder.get(), avif_edited.data, avif_edited.size),
AVIF_RESULT_OK);
ASSERT_EQ(avifDecoderParse(decoder.get()), AVIF_RESULT_BMFF_PARSE_FAILED);
}
//------------------------------------------------------------------------------
} // namespace
} // namespace avif
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
if (argc != 2) {
std::cerr << "There must be exactly one argument containing the path to "
"the test data folder"
<< std::endl;
return 1;
}
avif::data_path = argv[1];
return RUN_ALL_TESTS();
}