/src/libavif/tests/gtest/avif_fuzztest_dec.cc
Line | Count | Source |
1 | | // Copyright 2023 Google LLC |
2 | | // SPDX-License-Identifier: BSD-2-Clause |
3 | | // Decodes an arbitrary sequence of bytes. |
4 | | |
5 | | #include <algorithm> |
6 | | #include <cstdint> |
7 | | #include <limits> |
8 | | |
9 | | #include "avif/avif.h" |
10 | | #include "avif_fuzztest_helpers.h" |
11 | | #include "aviftest_helpers.h" |
12 | | #include "fuzztest/fuzztest.h" |
13 | | #include "gtest/gtest.h" |
14 | | |
15 | | using ::fuzztest::Arbitrary; |
16 | | |
17 | | namespace avif { |
18 | | namespace testutil { |
19 | | namespace { |
20 | | |
21 | | //------------------------------------------------------------------------------ |
22 | | |
23 | | void Parse(const std::string& arbitrary_bytes, bool is_persistent, |
24 | 8.23k | DecoderPtr decoder) { |
25 | 8.23k | ASSERT_FALSE(GetSeedDataDirs().empty()); // Make sure seeds are available. |
26 | | |
27 | 8.23k | const uint8_t* data = |
28 | 8.23k | reinterpret_cast<const uint8_t*>(arbitrary_bytes.data()); |
29 | 8.23k | avifIO* const io = avifIOCreateMemoryReader(data, arbitrary_bytes.size()); |
30 | 8.23k | if (io == nullptr) return; |
31 | 8.23k | io->persistent = is_persistent; |
32 | 8.23k | avifDecoderSetIO(decoder.get(), io); |
33 | | // No need to worry about decoding taking too much time or memory because |
34 | | // this test only exercises parsing. |
35 | 8.23k | decoder->imageSizeLimit = AVIF_DEFAULT_IMAGE_SIZE_LIMIT; |
36 | 8.23k | decoder->imageDimensionLimit = std::numeric_limits<uint32_t>::max(); |
37 | 8.23k | decoder->imageCountLimit = 0; |
38 | | |
39 | | // AVIF_RESULT_INTERNAL_ERROR means a broken invariant and should not happen. |
40 | 8.23k | ASSERT_NE(avifDecoderParse(decoder.get()), AVIF_RESULT_INTERNAL_ERROR); |
41 | 8.23k | } |
42 | | |
43 | | FUZZ_TEST(ParseAvifTest, Parse) |
44 | | .WithDomains(ArbitraryImageWithSeeds({AVIF_APP_FILE_FORMAT_AVIF}), |
45 | | /*is_persistent=*/Arbitrary<bool>(), |
46 | | ArbitraryAvifDecoderPossiblyNoContent()); |
47 | | |
48 | | //------------------------------------------------------------------------------ |
49 | | |
50 | | void Decode(const std::string& arbitrary_bytes, bool is_persistent, |
51 | 20.5k | DecoderPtr decoder) { |
52 | 20.5k | ASSERT_FALSE(GetSeedDataDirs().empty()); // Make sure seeds are available. |
53 | | |
54 | 20.5k | const uint8_t* data = |
55 | 20.5k | reinterpret_cast<const uint8_t*>(arbitrary_bytes.data()); |
56 | 20.5k | avifIO* const io = avifIOCreateMemoryReader(data, arbitrary_bytes.size()); |
57 | 20.5k | if (io == nullptr) return; |
58 | | // The Chrome's avifIO object is not persistent. |
59 | 20.5k | io->persistent = is_persistent; |
60 | 20.5k | avifDecoderSetIO(decoder.get(), io); |
61 | | |
62 | 20.5k | avifResult result = avifDecoderParse(decoder.get()); |
63 | | // AVIF_RESULT_INTERNAL_ERROR means a broken invariant and should not happen. |
64 | 20.5k | ASSERT_NE(result, AVIF_RESULT_INTERNAL_ERROR); |
65 | 20.5k | if (result != AVIF_RESULT_OK) return; |
66 | | |
67 | 30.7k | for (size_t i = 0; i < decoder->image->numProperties; ++i) { |
68 | 12.8k | const avifRWData& box_payload = decoder->image->properties[i].boxPayload; |
69 | | // Each custom property should be found as is in the input bitstream. |
70 | 12.8k | EXPECT_NE(std::search(data, data + arbitrary_bytes.size(), box_payload.data, |
71 | 12.8k | box_payload.data + box_payload.size), |
72 | 12.8k | data + arbitrary_bytes.size()); |
73 | 12.8k | } |
74 | | |
75 | 23.4k | while ((result = avifDecoderNextImage(decoder.get())) == AVIF_RESULT_OK) { |
76 | 5.59k | EXPECT_GT(decoder->image->width, 0u); |
77 | 5.59k | EXPECT_GT(decoder->image->height, 0u); |
78 | 5.59k | } |
79 | 17.8k | ASSERT_NE(result, AVIF_RESULT_INTERNAL_ERROR); |
80 | | |
81 | | // Loop once. |
82 | 17.8k | result = avifDecoderReset(decoder.get()); |
83 | 17.8k | ASSERT_NE(result, AVIF_RESULT_INTERNAL_ERROR); |
84 | 17.8k | if (result != AVIF_RESULT_OK) return; |
85 | 21.0k | while ((result = avifDecoderNextImage(decoder.get())) == AVIF_RESULT_OK) { |
86 | 4.53k | } |
87 | | ASSERT_NE(result, AVIF_RESULT_INTERNAL_ERROR); |
88 | 16.4k | } |
89 | | |
90 | | FUZZ_TEST(DecodeAvifTest, Decode) |
91 | | .WithDomains(ArbitraryImageWithSeeds({AVIF_APP_FILE_FORMAT_AVIF}), |
92 | | /*is_persistent=*/Arbitrary<bool>(), |
93 | | ArbitraryAvifDecoderPossiblyNoContent()); |
94 | | |
95 | | //------------------------------------------------------------------------------ |
96 | | |
97 | | } // namespace |
98 | | } // namespace testutil |
99 | | } // namespace avif |