/src/libjxl/tools/icc_codec_fuzzer.cc
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) the JPEG XL Project Authors. All rights reserved. |
2 | | // |
3 | | // Use of this source code is governed by a BSD-style |
4 | | // license that can be found in the LICENSE file. |
5 | | |
6 | | #include <jxl/memory_manager.h> |
7 | | |
8 | | #include <cstddef> |
9 | | #include <cstdint> |
10 | | #include <cstring> |
11 | | |
12 | | #include "lib/jxl/enc_icc_codec.h" |
13 | | |
14 | | #ifdef JXL_ICC_FUZZER_SLOW_TEST |
15 | | #include "lib/jxl/base/span.h" |
16 | | #include "lib/jxl/dec_bit_reader.h" |
17 | | #endif |
18 | | |
19 | | #include "lib/jxl/base/status.h" |
20 | | #include "lib/jxl/padded_bytes.h" |
21 | | #include "lib/jxl/test_utils.h" |
22 | | |
23 | | namespace jxl { |
24 | | Status PredictICC(const uint8_t* icc, size_t size, PaddedBytes* result); |
25 | | Status UnpredictICC(const uint8_t* enc, size_t size, PaddedBytes* result); |
26 | | } // namespace jxl |
27 | | |
28 | | namespace { |
29 | | |
30 | | using ::jxl::PaddedBytes; |
31 | | |
32 | | #ifdef JXL_ICC_FUZZER_SLOW_TEST |
33 | | using ::jxl::BitReader; |
34 | | using ::jxl::Span; |
35 | | #endif |
36 | | |
37 | 4.14k | int DoTestOneInput(const uint8_t* data, size_t size) { |
38 | | #if defined(JXL_ICC_FUZZER_ONLY_WRITE) |
39 | | bool read = false; |
40 | | #elif defined(JXL_ICC_FUZZER_ONLY_READ) |
41 | | bool read = true; |
42 | | #else |
43 | | // Decide whether to test the reader or the writer (both use parsing) |
44 | 4.14k | if (!size) return 0; |
45 | 4.14k | bool read = data[0] == 0; |
46 | 4.14k | data++; |
47 | 4.14k | size--; |
48 | 4.14k | #endif |
49 | 4.14k | JxlMemoryManager* memory_manager = jxl::test::MemoryManager(); |
50 | | |
51 | | #ifdef JXL_ICC_FUZZER_SLOW_TEST |
52 | | // Including JPEG XL LZ77 and ANS compression. These are already fuzzed |
53 | | // separately, so it is better to disable JXL_ICC_FUZZER_SLOW_TEST to focus on |
54 | | // the ICC parsing. |
55 | | if (read) { |
56 | | // Reading parses the compressed format. |
57 | | BitReader br(Bytes(data, size)); |
58 | | std::vector<uint8_t> result; |
59 | | (void)jxl::test::ReadICC(&br, &result); |
60 | | (void)br.Close(); |
61 | | } else { |
62 | | // Writing parses the original ICC profile. |
63 | | PaddedBytes icc{memory_manager}; |
64 | | icc.assign(data, data + size); |
65 | | BitWriter writer{memory_manager}; |
66 | | // Writing should support any random bytestream so must succeed, make |
67 | | // fuzzer fail if not. |
68 | | JXL_ASSERT(jxl::WriteICC(icc, &writer, 0, nullptr)); |
69 | | } |
70 | | #else // JXL_ICC_FUZZER_SLOW_TEST |
71 | 4.14k | if (read) { |
72 | | // Reading (unpredicting) parses the compressed format. |
73 | 1.19k | PaddedBytes result{memory_manager}; |
74 | 1.19k | (void)jxl::UnpredictICC(data, size, &result); |
75 | 2.95k | } else { |
76 | | // Writing (predicting) parses the original ICC profile. |
77 | 2.95k | PaddedBytes result{memory_manager}; |
78 | | // Writing should support any random bytestream so must succeed, make |
79 | | // fuzzer fail if not. |
80 | 2.95k | JXL_ASSERT(jxl::PredictICC(data, size, &result)); |
81 | 2.95k | PaddedBytes reconstructed{memory_manager}; |
82 | 2.95k | JXL_ASSERT(jxl::UnpredictICC(result.data(), result.size(), &reconstructed)); |
83 | 2.95k | JXL_ASSERT(reconstructed.size() == size); |
84 | 2.95k | JXL_ASSERT(memcmp(data, reconstructed.data(), size) == 0); |
85 | 2.95k | } |
86 | 4.14k | #endif // JXL_ICC_FUZZER_SLOW_TEST |
87 | 4.14k | return 0; |
88 | 4.14k | } |
89 | | |
90 | | } // namespace |
91 | | |
92 | 32.6k | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { |
93 | 32.6k | return DoTestOneInput(data, size); |
94 | 32.6k | } |
95 | | |
96 | 0 | void TestOneInput(const std::vector<uint8_t>& data) { |
97 | 0 | DoTestOneInput(data.data(), data.size()); |
98 | 0 | } |
99 | | |
100 | | FUZZ_TEST(IccCodecFuzzTest, TestOneInput); |