/src/libavif/tests/gtest/avif_fuzztest_read_image.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright 2023 Google LLC |
2 | | // SPDX-License-Identifier: BSD-2-Clause |
3 | | // |
4 | | // Tests the jpeg/png/y4m reading code from avifenc. |
5 | | |
6 | | #include <fstream> |
7 | | #include <iostream> |
8 | | #include <string> |
9 | | #include <vector> |
10 | | |
11 | | #include "avif/avif.h" |
12 | | #include "avif_fuzztest_helpers.h" |
13 | | #include "aviftest_helpers.h" |
14 | | #include "avifutil.h" |
15 | | #include "fuzztest/fuzztest.h" |
16 | | #include "gtest/gtest.h" |
17 | | |
18 | | using ::fuzztest::Arbitrary; |
19 | | using ::fuzztest::ElementOf; |
20 | | |
21 | | namespace avif { |
22 | | namespace testutil { |
23 | | namespace { |
24 | | |
25 | | //------------------------------------------------------------------------------ |
26 | | |
27 | 2.13k | std::string FileFormatToString(avifAppFileFormat file_format) { |
28 | 2.13k | switch (file_format) { |
29 | 0 | case AVIF_APP_FILE_FORMAT_UNKNOWN: |
30 | 0 | return "unknown"; |
31 | 0 | case AVIF_APP_FILE_FORMAT_AVIF: |
32 | 0 | return "AVIF"; |
33 | 33 | case AVIF_APP_FILE_FORMAT_PNG: |
34 | 33 | return "PNG"; |
35 | 2.09k | case AVIF_APP_FILE_FORMAT_JPEG: |
36 | 2.09k | return "JPEG"; |
37 | 7 | case AVIF_APP_FILE_FORMAT_Y4M: |
38 | 7 | return "Y4M"; |
39 | 0 | default: |
40 | 0 | assert(false); |
41 | 0 | return "unknown"; |
42 | 2.13k | } |
43 | 2.13k | } |
44 | | |
45 | | void ReadImageFile(const std::string& arbitrary_bytes, |
46 | | avifPixelFormat requested_format, int requested_depth, |
47 | | avifChromaDownsampling chroma_downsampling, |
48 | | bool ignore_color_profile, bool ignore_exif, bool ignore_xmp, |
49 | | bool allow_changing_cicp, bool ignore_gain_map, |
50 | 8.00k | avifMatrixCoefficients matrix_coefficients) { |
51 | 8.00k | ASSERT_FALSE(GetSeedDataDirs().empty()); // Make sure seeds are available. |
52 | | |
53 | | // Write the byte stream to a temp file since avifReadImage() takes a file |
54 | | // path as input. |
55 | 8.00k | const std::string file_path = testing::TempDir() + "inputimage"; |
56 | 8.00k | std::ofstream out(file_path); |
57 | 8.00k | out << arbitrary_bytes; |
58 | 8.00k | out.close(); |
59 | | |
60 | 8.00k | uint32_t out_depth; |
61 | 8.00k | avifAppSourceTiming timing; |
62 | 8.00k | ImagePtr avif_image(avifImageCreateEmpty()); |
63 | 8.00k | avif_image->matrixCoefficients = matrix_coefficients; |
64 | | |
65 | | // OSS-Fuzz limits the allocated memory to 2560 MB. |
66 | 8.00k | constexpr uint32_t kMaxMem = 2560u * 1024 * 1024; |
67 | | // Consider at most four planes of 16-bit samples. |
68 | 8.00k | constexpr uint32_t kMaxImageSize = |
69 | 8.00k | kMaxMem / (AVIF_PLANE_COUNT_YUV + 1) / sizeof(uint16_t); |
70 | | // Reduce the limit further to include pixel buffer copies and other memory |
71 | | // allocations. |
72 | 8.00k | constexpr uint32_t kImageSizeLimit = kMaxImageSize / 4; |
73 | | // SharpYUV is computationally expensive. Avoid timeouts. |
74 | 8.00k | const uint32_t imageSizeLimit = |
75 | 8.00k | (chroma_downsampling == AVIF_CHROMA_DOWNSAMPLING_SHARP_YUV && |
76 | 8.00k | requested_format == AVIF_PIXEL_FORMAT_YUV420) |
77 | 8.00k | ? kImageSizeLimit / 8 |
78 | 8.00k | : kImageSizeLimit; |
79 | | |
80 | 8.00k | const avifAppFileFormat file_format = avifReadImage( |
81 | 8.00k | file_path.c_str(), AVIF_APP_FILE_FORMAT_UNKNOWN /* guess format */, |
82 | 8.00k | requested_format, requested_depth, chroma_downsampling, |
83 | 8.00k | ignore_color_profile, ignore_exif, ignore_xmp, allow_changing_cicp, |
84 | 8.00k | ignore_gain_map, imageSizeLimit, avif_image.get(), &out_depth, &timing, |
85 | 8.00k | /*frameIter=*/nullptr); |
86 | | |
87 | 8.00k | if (file_format != AVIF_APP_FILE_FORMAT_UNKNOWN) { |
88 | 2.13k | EXPECT_GT(avif_image->width, 0); |
89 | 2.13k | EXPECT_GT(avif_image->height, 0); |
90 | | |
91 | 2.13k | if (requested_depth != 0 && file_format != AVIF_APP_FILE_FORMAT_Y4M) { |
92 | 1.54k | EXPECT_EQ(avif_image->depth, requested_depth); |
93 | 1.54k | } |
94 | 2.13k | if (file_format != AVIF_APP_FILE_FORMAT_Y4M) { |
95 | 2.13k | EXPECT_EQ(avif_image->yuvFormat, requested_format); |
96 | 2.13k | } |
97 | 2.13k | if (ignore_color_profile) { |
98 | 1.06k | EXPECT_EQ(avif_image->icc.size, 0); |
99 | 1.06k | } |
100 | 2.13k | if (ignore_exif) { |
101 | 1.05k | EXPECT_EQ(avif_image->exif.size, 0); |
102 | 1.05k | } |
103 | 2.13k | if (ignore_xmp) { |
104 | 1.03k | EXPECT_EQ(avif_image->xmp.size, 0); |
105 | 1.03k | } |
106 | 2.13k | std::cout << "Decode successful (" << FileFormatToString(file_format) |
107 | 2.13k | << ")\n"; |
108 | 2.13k | } |
109 | 8.00k | } |
110 | | |
111 | | FUZZ_TEST(ReadImageFuzzTest, ReadImageFile) |
112 | | .WithDomains(ArbitraryImageWithSeeds({AVIF_APP_FILE_FORMAT_JPEG, |
113 | | AVIF_APP_FILE_FORMAT_PNG, |
114 | | AVIF_APP_FILE_FORMAT_Y4M}), |
115 | | ArbitraryPixelFormat(), |
116 | | /*requested_depth=*/ElementOf({0, 8, 10, 12}), |
117 | | ElementOf({AVIF_CHROMA_DOWNSAMPLING_AUTOMATIC, |
118 | | AVIF_CHROMA_DOWNSAMPLING_FASTEST, |
119 | | AVIF_CHROMA_DOWNSAMPLING_BEST_QUALITY, |
120 | | AVIF_CHROMA_DOWNSAMPLING_AVERAGE, |
121 | | AVIF_CHROMA_DOWNSAMPLING_SHARP_YUV}), |
122 | | /*ignore_color_profile=*/Arbitrary<bool>(), |
123 | | /*ignore_exif=*/Arbitrary<bool>(), |
124 | | /*ignore_xmp=*/Arbitrary<bool>(), |
125 | | /*allow_changing_cicp=*/Arbitrary<bool>(), |
126 | | /*ignore_gain_map=*/Arbitrary<bool>(), |
127 | | ElementOf({AVIF_MATRIX_COEFFICIENTS_IDENTITY, |
128 | | AVIF_MATRIX_COEFFICIENTS_BT709, |
129 | | AVIF_MATRIX_COEFFICIENTS_UNSPECIFIED, |
130 | | AVIF_MATRIX_COEFFICIENTS_FCC, |
131 | | AVIF_MATRIX_COEFFICIENTS_BT470BG, |
132 | | AVIF_MATRIX_COEFFICIENTS_BT601, |
133 | | AVIF_MATRIX_COEFFICIENTS_SMPTE240, |
134 | | AVIF_MATRIX_COEFFICIENTS_YCGCO, |
135 | | AVIF_MATRIX_COEFFICIENTS_BT2020_NCL, |
136 | | AVIF_MATRIX_COEFFICIENTS_BT2020_CL, |
137 | | AVIF_MATRIX_COEFFICIENTS_SMPTE2085, |
138 | | AVIF_MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL, |
139 | | AVIF_MATRIX_COEFFICIENTS_CHROMA_DERIVED_CL, |
140 | | AVIF_MATRIX_COEFFICIENTS_ICTCP})); |
141 | | |
142 | | //------------------------------------------------------------------------------ |
143 | | |
144 | | } // namespace |
145 | | } // namespace testutil |
146 | | } // namespace avif |